Функция fread читает а функция fwrite пишет в файл данные начиная с позиции
Указатель ( resource ) на файл, обычно создаваемый с помощью функции fopen() .
length указывает размер прочитанных данных в байтах.
Решение
Вау, много проблем в вашем коде. Давайте займемся ими один за другим.
Как упоминалось в разделе «Размотка», режим, который вы используете для открытия файла, кажется неправильным в отношении того, что вы пытаетесь сделать. Например, вы пытаетесь читать из файла, который открыт для только для записи.
Вы используете fwrite ошибочно. Идет fwrite(pointer to data, size of each data, number of data, FILE pointer); ,
Вы используете fseek ошибочно. Я вижу, ты запутался с offset параметр. Это смещение определяет обозначенное расстояние от origin указано в качестве последнего аргумента fseek , Поэтому, если вы в SEEK_END , вы должны двигаться назад, имея offset быть отрицательным числом.
Я сделал эти изменения сам, и теперь это работает. Выход: q 123 2111 e
Вот милый маленький Веб-сайт для тебя тоже. Помог мне с твоей проблемой.
Спасибо за чтение.
Примеры
// получает содержимое файла в строку
$filename = "/usr/local/something.txt" ;
$handle = fopen ( $filename , "r" );
$contents = fread ( $handle , filesize ( $filename ));
fclose ( $handle );
?>?php
На системах, которые различают бинарные и текстовые файлы (к примеру, Windows), файл должен быть открыт с использованием флага 'b' в параметре mode функции fopen() .
$filename = "c:\\files\\somepic.jpg" ;
$handle = fopen ( $filename , "rb" );
$contents = fread ( $handle , filesize ( $filename ));
fclose ( $handle );
?>?php
При чтении чего-либо отличного от локальных файлов, например потоков, возвращаемых при чтении удалённых файлов или из popen() и fsockopen() , чтение остановится после того, как пакет станет доступным. Это означает, что вы должны собирать данные вместе по кусочкам, как показано на примере ниже.
$handle = fopen ( "http://www.example.com/" , "rb" );
$contents = stream_get_contents ( $handle );
fclose ( $handle );
?>?php
$handle = fopen ( "http://www.example.com/" , "rb" );
if ( FALSE === $handle ) exit( "Не удалось открыть поток по url адресу" );
>
while (! feof ( $handle )) $contents .= fread ( $handle , 8192 );
>
fclose ( $handle );
?>
Примечания
Замечание:
Если вы просто хотите получить содержимое файла в виде строки, используйте file_get_contents() , так как эта функция намного производительнее, чем код описанный выше.
Замечание:
Учтите, что fread() читает, начиная с текущей позиции файлового указателя. Используйте функцию ftell() для нахождения текущей позиции указателя и функцию rewind() для перемотки позиции указателя в начало.
Возвращаемые значения
Возвращает прочтённую строку или false в случае возникновения ошибки.
2 ответа 2
fread/fwrite функции читают/пишут данные в бинарном формате. Если хочется человеко-читаемый (текстовый) формат, то можно использовать fscanf/fprintf вместо fread/fwrite соответственно.
Приведённый в вопросе код должен работать как есть.
Что конкретно fwrite запишет на диск, может зависеть от платформы (размер типа (LLP64, LP64 модели), порядок байтов, и даже побитовое представление типов (дополнительный код, обратный код), выравнивание типов).
Например, если файл скопировать на другую платформу, то не обязательно что fread сможет его прочитать корректно.
На моей машине test файл содержит:
Первая колонка, нумерует байты, в каждой строке по 16 байт, представленных командой xxd ввиде шестнадцатеричных чисел (каждые две цифры соответствуют одному байту). Самая правая колонка показывает печатаемые байты (точка используется для непечатаемых в ascii символов).
Вот байты соответствующие каждому значению:
Можно сразу сказать, что int является 32-битным типом (4 байта, предполагая 1 байт = 8 бит), а long 64-битным типом (что верно для lp64 модели) с порядком байтов от младшего с старшему (little-endian) на моей машине.
Если записать байты для i и l в порядке от старшего к младшему (big-endian) как обычно числа записаны на бумаге пишут:
- int i 00000065 в шестнадцатеричной системе соответствует 101 в десятичной системе(6516 = 10110), что является корректным значением для i
- long l 000000000001e08f в шестнадцатеричной системе соответствует 123023 в десятичной системе (1e08f16 = 12302310), что также верно.
Число d записано как число двойной точности в IEEE 754 формате --
d = ±знак · (1 + мантисса / 2 52 ) · 2 порядок − 1023 :
(cнова переписал байты от старшего к младшему) Или в двоичной системе -- все 64 бита числа d :
Самый левый бит это знак, в данном случае он 0 , то есть d является положительным, затем 11 бит порядок = 100000000102 = 102610, оставшиеся 52 бита мантисса:
1000011101011100001010001111010111000010100011110112
= 238127830297215010
= 875c28f5c28f616
d = (1 + 2381278302972150 / 2 52 ) · 2 1026 − 1023
= 3442438965171323 / 281474976710656
= 12.23
Двоичный файл это последовательность данных не текстового формата. Поэтому редактировать файл в текстовом редакторе невозможно. С другой стороны такой файл может иметь меньший объем, а для редактирования могут быть предназначены специальные редакторы.
Чтение и запись потока байтов выполняют функции fread и fwrite .
fread(void *buffer, size, count, FILE *f);
Функция считывает count элементов длиной size байтов в буфер, заданный указателем buffer , из потока f .
Функция возвращает количество прочитанных элементов, которое может быть меньше count , если при чтении произошла ошибка или встретился конец файла.
fwrite(const void *p, size, n, FILE *f);
Функция записывает n элементов длиной size байт из буфера, заданного указателем р, в поток f . Возвращает число записанных элементов.
Пример, демонстрирующий работу с этими функциями:
struct Client
char SurName[27];
char Name[21];
char SecName[21];
FILE *stream;
Client AClient , RClient ;
//Открываем файл для вывода
if ((stream = fopen("d:\\SAMPLE.DAT", "wb")) == NULL)
printf ( RUS ("Файл не открыт для записи\ n "));
AClient.Num = 1;
strcpy(AClient.SurName,"Petrov");
strcpy(AClient.Name, "Petr");
strcpy(AClient.SecName, "Petrovich");
// Запись структуры в файл
//Закрываем файл
fclose ( stream ) ;
//Открываем файл для чтения
if ((stream = fopen ("d:\\SAMPLE.DAT ", "rb") ) == NULL)
printf ( RUS ("Файл не открыт для чтения\ n ")) ;
//Закрываем файл
fclose (stream) ;
printf ("The structure contains : \n ");
printf ("Num = %d SurName = %s Name = %s SecName = %s",
RClient . Num , RClient . SurName , RClient . Name , RClient . SecName ) ;
В этом примере вначале файл открывается для записи в него значений полей из структуры AClient , затем этот файл открывается для чтения содержащейся в нем информации в структуру RClient . После чего поля этой структуры выводятся на экран. При выполнении программа выводит на экран:
The structure contains:
Num = 1 SurName = Petrov Name = Petr SecName = Petrovich
Функции позиционирования
Операции ввода/вывода выполняются, начиная с текущей позиции потока, определяемой положением (значением) указателя потока. Указатель устанавливается при открытии на начало или конец файла (в соответствии с режимом открытия ² a ² , ² a + ² ) и изменяется автоматически после каждой операции ввода/вывода. Текущее положение указателя можно получить с помощью функций ftell и fgetpos и задать явным образом с помощью функций fseek , fsetpos и rewind . Эти функции нельзя использовать для стандартных потоков.
long int ftell ( FILE * f );
Функция возвращает текущую позицию в файле, связанном с потоком f , как длинное целое. В случае ошибки она возвращает –1.
int fgetpos ( FILE * f , fpos _ t * pos );
Функция возвращает текущую позицию в файле, связанном с потоком f , и копирует значение по адресу pos . Это значение позднее может использоваться функцией fsetpos . Возвращаемое значение имеет тип fpos _ t .
int fseek(FILE *f, long off, int org);
Функция перемещает текущую позицию в файле, связанном с потоком f , на позицию off , отсчитываемую от значения org , которое должно быть равно одной из трех констант, определенных в < stdio . h >:
SEEK _ CUR ( =1 ) – от текущей позиции указателя;
SEEK _ END ( =2 ) – от конца файла;
SEEK _ SET ( =0 ) – от начала файла.
Функция возвращает 0 , если указатель текущей позиции в файле успешно изменен, и отличное от 0 значение в противном случае.
int fsetpos(FILE *f, const fpos_t *pos);
Функция перемещает текущую позицию в файле, связанном с потоком f , на позицию * pos , предварительно полученную с помощью функции fgetpos .
void rewind ( FILE * f );
Функция очищает флаги ошибок в потоке f и устанавливает текущую позицию на начало файла.
Функции позиционирования позволяют провести вывод непосредственно после ввода, не закрывая файл. Для этого их записывают между функциями ввода и вывода. Однако рекомендуется всегда явным образом закрывать потоки, открытые для записи, чтобы избежать потери данных.
Рассмотрим пример, демонстрирующий работу этих функций:
struct Client
char SurName[27];
char Name[21];
char SecName[21];
FILE *stream;
Client AClient , RClient ;
//Открываем файл для вывода
if ((stream = fopen("d:\\SAMPLE.DAT", "wb")) == NULL)
printf ( RUS ("Файл не открыт для записи\ n "));
AClient.Num = 1;
strcpy(AClient.SurName,"Petrov");
strcpy(AClient.Name, "Petr");
strcpy(AClient.SecName, "Petrovich");
// Запись структуры в файл
long int pos = ftell(stream);
//Выводим позицию файла и длину структуры
printf("The file pos = %d structure length = %d\n", pos, sizeof(AClient));
//Репозиционируем файл
rewind ( stream );
//Открываем файл для чтения
if ((stream = fopen ("d:\\SAMPLE.DAT ", "rb") ) == NULL)
printf ( RUS ("Файл не открыт для чтения\ n ")) ;
//Закрываем файл
fclose (stream) ;
printf ("The structure contains : \n ");
printf ("Num = %d SurName = %s Name = %s SecName = %s",
RClient . Num , RClient . SurName , RClient . Name , RClient . SecName ) ;
Этот пример представляет собой модификацию предыдущего примера. Здесь файл открывается лишь однажды, и после записи в него структуры на экран выводится значение указателя позиции и длины структуры. При выполнении программа выводит на экран:
The file pos = 76 structure length = 76
The structure contains:
Num = 1 SurName = Petrov Name = Petr SecName = Petrovich
Пример работы с потоками
Допустим, что в файле хранятся сведения о мониторах. В каждой строке указан тип, оптовая и розничная цены и примечание. Для простоты данные в каждой строке записаны единообразно: первые 20 символов занимает тип монитора, далее по 5 символов целые числа, представляющие оптовую и розничную цены, затем примечание длиной не более 40 символов.
Приведенная ниже программа построчно считывает данные из текстового файла в буферную переменную s , затем формирует из них структуру m on и записывает ее в двоичном режиме в выходной файл. Далее производится считывание из этого файла произвольной записи.
FILE * fi , * fo ;
if((fi = fopen("d:\\file.txt", "r")) == 0)
if((fo = fopen("d:\\binfile.out", "w+b")) == 0)
const int dl = 80;
char type[20];
int opt, rozn;
char comm [40];
int kol = 0; // Количество записей в файле
while ( fgets ( s , dl , fi )) // Преобразование строки в структуру:
Я хочу написать три символа в файл, затем структуру, а затем еще один символ.
Наконец, я хотел бы прочитать символ перед структурой, саму структуру, символ после структуры и отобразить их на экране.
Вместо этого результата:
Я получаю этот результат:
Я не знаю, что я делаю не так. Я записываю байты в файл, читаю их обратно и отображаю на экране. Что идет не так?
Возвращаемые значения
Возвращает прочтённую строку или false в случае возникновения ошибки.
User Contributed Notes 31 notes
I couldn't get some of the previous resume scripts to work with Free Download Manager or Firefox. I did some clean up and modified the code a little.
function dl_file_resumable ( $file , $is_resume = TRUE )
//First, see if the file exists
if (! is_file ( $file ))
die( "404 File not found!" );
>
//Gather relevent info about file
$size = filesize ( $file );
$fileinfo = pathinfo ( $file );
$file_extension = strtolower ( $path_info [ 'extension' ]);
//This will set the Content-Type to the appropriate setting for the file
switch( $file_extension )
case 'exe' : $ctype = 'application/octet-stream' ; break;
case 'zip' : $ctype = 'application/zip' ; break;
case 'mp3' : $ctype = 'audio/mpeg' ; break;
case 'mpg' : $ctype = 'video/mpeg' ; break;
case 'avi' : $ctype = 'video/x-msvideo' ; break;
default: $ctype = 'application/force-download' ;
>
//figure out download piece from range (if set)
list( $seek_start , $seek_end ) = explode ( '-' , $range , 2 );
//set start and end based on range (if set), else set defaults
//also check for invalid ranges.
$seek_end = (empty( $seek_end )) ? ( $size - 1 ) : min ( abs ( intval ( $seek_end )),( $size - 1 ));
$seek_start = (empty( $seek_start ) || $seek_end < abs ( intval ( $seek_start ))) ? 0 : max ( abs ( intval ( $seek_start )), 0 );
header ( 'Accept-Ranges: bytes' );
header ( 'Content-Range: bytes ' . $seek_start . '-' . $seek_end . '/' . $size );
>
//headers for IE Bugs (is this necessary?)
//header("Cache-Control: cache, must-revalidate");
//header("Pragma: public");
header ( 'Content-Type: ' . $ctype );
header ( 'Content-Disposition: attachment; filename keyword">. $filename . '"' );
header ( 'Content-Length: ' .( $seek_end - $seek_start + 1 ));
//open the file
$fp = fopen ( $file , 'rb' );
//seek to start of missing part
fseek ( $fp , $seek_start );
//start buffered download
while(! feof ( $fp ))
//reset time limit for big files
set_time_limit ( 0 );
print( fread ( $fp , 1024 * 8 ));
flush ();
ob_flush ();
>
Файловая система ANSI С предоставляет две функции, позволяющие читать и писать блоки дан¬ных - fread() и fwrite(). Они имеют следующие прототипы:
size_t fread(void *буфер, size_t число_байту size_t объем, FILE *fp);
size_t fwrite(const void *буфер, size_t число_байт, size_t объем, FILE *fp);
В случае fread() буфер - это указатель на область памяти, которая получает данные из файла. В случае fwrite() буфер - это указатель на информацию, записываемую в файл. Длина каждого элемента в байтах определяется в число_байт. Аргумент объем определяет, сколько элементов (каж¬дый длиной число_байт) будет прочитано или записано. Наконец, fp - это файловый указатель на ранее открытый поток.
Функция fread() возвращает число прочитанных элементов. Данное значение может быть мень¬ше, чем объем, если был достигнут конец файла или произошла ошибка. Функция fwrite() возвра¬щает число записанных элементов. Данное значение равно объем, если не возникла ошибка.
Если файл был открыт для двоичных данных, то fread() и fwrite() могут читать и писать любой тип информации. Например, следующая программа записывает float в файл:
Как иллюстрирует данная программа, буфер может быть (а чаще всего это так и есть) простой переменной.
Одно из наиболее полезных применений fread() и fwrite() - это чтение и запись блоков данных типа массивов или структур. Например, следующий фрагмент записывает содержимое массива ве¬щественных чисел balance в файл balance, используя один оператор fwrite(). Далее она читает мас¬сив, используя один оператор fread(), и выводит его содержимое.
/* открытие на запись */
if((fp=fopen("balance", "wb"))==NULL) printf("Cannot open file.");
return 1;
>
for(i=0; i
/* сохранение за раз всего массива balance */
fwrite(balance, sizeof balance, 1, fp) ;
fclose(fp);
/* открытие для чтения */
if((fp=fopen("balance","rb"))==NULL) printf("cannot open file");
return 1;
>
/* чтение за раз всего массива balance */
fread(balance, sizeof balance, 1, fp);
Использование fread() и fwrite() для чтения или записи сложных данных более эффективно, чем использование повторяющихся вызовов getc() и putc().
Пример взял с сайта для изучения C++. При записи в файл в нем самом отображается ерунда, но не то, что надо. С чего бы это?
Смотрите также
- fwrite() - Бинарно-безопасная запись в файл
- fopen() - Открывает файл или URL
- fsockopen() - Открывает соединение с интернет-сокетом или доменным сокетом Unix
- popen() - Открывает файловый указатель процесса
- fgets() - Читает строку из файла
- fgetss() - Читает строку из файла и удаляет HTML-теги
- fscanf() - Обрабатывает данные из файла в соответствии с форматом
- file() - Читает содержимое файла и помещает его в массив
- fpassthru() - Выводит все оставшиеся данные из файлового указателя
- ftell() - Возвращает текущую позицию указателя чтения/записи файла
- rewind() - Сбрасывает курсор файлового указателя
- unpack() - Распаковать данные из бинарной строки
Другие решения
Во-первых, как было указано, вы должны открыть файл в двоичном
Режим. Даже тогда, просто сбрасывая байты struct средства
что вы не сможете прочитать его правильно некоторое время в
будущее. Но пока вы читаете из того же процесса, это
должно быть хорошо.
Настоящая проблема в том, что вы делаете со всеми fseek :
до первого fread Вы делаете fseek за пределами
файл. Любое чтение с этой позиции гарантированно потерпит неудачу.
Вы действительно должны проверить состояние файла и убедиться, что
fread успешно, прежде чем получить доступ к любому из значений, которые вы
читать. Если это не удалось, доступ к переменным (по крайней мере, те, в
stuff ) неопределенное поведение; скорее всего, вы получите
случайный мусор.
Ты первый fseek должно быть в начале файла, или
еще:
Если вы только что прочитали структуру, то второй fseek является
также не нужно. (В вашем случае это означает, что окончательный
'e' правильно читать.)
Вы должны открыть свой файл в двоичном режиме, чтобы это работало.
Ваш желаемый результат также немного неясен, если он не начинается с трех символов 'z' , 's' а также 'q' , а то есть целые числа? Обратите внимание, что целые числа могут появиться с заменой байтов, если вы находитесь на машине с прямым порядком байтов.
Чтобы помочь отладить код, вы должны добавить проверку возвращаемого значения ко всем вызовам ввода / вывода, поскольку ввод / вывод может завершиться неудачей. Также обратите внимание, что sizeof (char) всегда 1 так что не очень полезно так писать.
Читайте также: