Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C++ Builder > Проблема со считыванием файла


Автор: Свят86 28.8.2012, 16:49
столкнулся с такой проблемой и не могу найти ей объяснение.
есть код читающий содержимое двоичного файла:
Код

#include <fcntl.h>
#include <sys\stat.h>
char *bytef;
void read_f()
{
    FILE *openfile;
    openfile=fopen(path.c_str(),"rb");
    if (openfile)
    {
        struct stat statbuf;
        stat(path.c_str(),&statbuf);
        bytef=new char[statbuf.st_size];
        fread (bytef,statbuf.st_size,1,openfile);
    };
fclose(openfile);
}


чтение происходит без ошибок, но сделав паузу и просматривая содержимое переменной bytef наблюдаю
появление символов '\n' там где их в реале нет! при записи содержимого переменной в файл, обнаружил закономерность:
символ '\n' , 0D  в шестнадцатиречиной системе, появляется только перед символом 0A который непечатаемый, но в файле есть!
в переменной  bytef он не виден, но в ней он фактически есть и в дальнейшем обрабатывается!  как быть?

Добавлено через 9 минут и 8 секунд
только что сделал через  handle open read ,  все равно та же бяка...

Автор: Dem_max 28.8.2012, 17:02
Все правильно, если в файле есть эти символы то они считаются в буффер.

Автор: Свят86 28.8.2012, 17:35
есть символ 0A а вот символа 0D нет! он дописывается перед 0A!!!

Автор: Dem_max 28.8.2012, 19:26
Запиши буффер обратно в файл, и сравни если 2 файла одинаковы то значит все правильно в буффер считалось

Автор: Свят86 28.8.2012, 20:53
в первом посте написано: "при записи содержимого переменной в файл, обнаружил закономерность:
символ '\n' , 0D  в шестнадцатиречиной системе, появляется только перед символом 0A который непечатаемый, но в файле есть!"

то есть по факту у меня в выходном файле получается больше байт ровно на количество символов 0A! и перед ним перед каждым появляется 0D!

пробовал читать файл в void *bytef  все равно! и писать пробовал в файл по разному! просто мистика какая-то...а мне это принципиально важно!
потом все байты перегоняются в двоичную систему и ведется работа с набором "0" и "1"!  не хочется делать функцию которая будет 0D удалять, ведь и так все должно работать правильно!

Добавлено через 5 минут и 25 секунд
и еще столкнулся с бякой: в AnsiString string_bit данные "0101110011100111111111111101010100101"
string_bit.LastDelimiter("111111") возвращает номер последнего символа, а не 20 как должен был! ничего вообще не понимаю...
постоянно работаю с .Pos()  .LastDelimiter() .SubString()  никогда подобных проблем не было!

Автор: xvr 29.8.2012, 18:14
Цитата(Свят86 @  28.8.2012,  16:49 Найти цитируемый пост)
при записи содержимого переменной в файл, обнаружил закономерность:

Ну так и смотрите код записи в файл. 99% ошибка в формате создания файла - стоит "w" (или "wt"), а надо "wb"



Цитата(Свят86 @  28.8.2012,  20:53 Найти цитируемый пост)
string_bit.LastDelimiter("111111") возвращает номер последнего символа, а не 20 как должен был!

С чего бы ему возвращать 20? У вас же последний символ '1' - вот его и возвращает. 
Смотри комент на функцию LastDelimiter -

Цитата

LastDelimiter returns the byte index in S of the rightmost whole character that matches any character in Delimiters (except null (#0)). S may contain multibyte characters; Delimiters must contain only single byte non-null characters.
Example: LastDelimiter('\.:', 'c:\filename.ext') returns 12. 
У вас все эти "any character" сплошные единицы  smile 

Автор: Свят86 30.8.2012, 08:07
на запись стоит все правильно! к тому же добавление '\n' можно посмотреть в буфере! мне уже разъяснили отчего это!

"Тут разница между бинарным чтением/записью и текстовым. При текстовом чтении/записи перевод строки в Windows и DOS состоит из двух символов: \r\n (13 и 10), в UNIX - из одного \n (10), в Mac OS - из одного \r (13). Именно 0D - это '\r', а '\n' - 0A. При текстовам чтении/записи \r\n обрабатываются в Windows как один символ '\n', при бинарном - как два байта со значениями 0D и 0A. Поэтому, если в текстовом файле делается перевод строки, то это добавляет, для бинарного чтения, дополнительные два байта."
 
а в LastDelimiter("111111") у меня же строка в " " а не в ' ' почему то считал что ищет такую последовательность в файле... и всегда работало... может просто примеры были такие что не давало косяков, а тут дало! smile

Автор: xvr 30.8.2012, 08:52
Цитата(Свят86 @  30.8.2012,  08:07 Найти цитируемый пост)
на запись стоит все правильно!
Нет, вы же сами дальше пишете -


Цитата(Свят86 @  30.8.2012,  08:07 Найти цитируемый пост)
Тут разница между бинарным чтением/записью и текстовым.

Именно так и есть. А 2й параметр в fopen и выбирает режим чтения/записи - "wt" (или просто "w") - текстовая запись, а "wb" - бинарная. 
Вы же на чтение поставили "rb" - а это именно бинарное чтение (не текстовое)

Цитата(Свят86 @  30.8.2012,  08:07 Найти цитируемый пост)
а в LastDelimiter("111111") у меня же строка в " " 

Вам же чистым английским языком написали - разделитель, это любой символ из поданной строки (причем только один символ), а не вся строка целиком

Цитата(Свят86 @  30.8.2012,  08:07 Найти цитируемый пост)
и всегда работало...

С таким разделителем - вряд ли  smile 

Автор: Свят86 30.8.2012, 09:58
с LastDelimiter все понятно, мой косяк! smile
а вот с чтением записью... у меня бинарный файл, в нем встречается практически вся таблица ASCII и символ '\n' как и остальные не несут своего
привычного значения! изначально был набор нулей и единиц, которые что-то обозначают, а при записи их в файл само собой получились байты! smile
там нет никаких новых строк, это просто набор нулей и единиц! я его читаю "rb" если читать "rt", то там и трети данных в буфере не окажется!
пишу я тоже в "rb" и пробовал писать в "rt" так как буфер у меня уже есть заполненный! так вот и в "rb" и в "rt" при записи перед 0A появляется 0D!
и если из буфера вырезать 0D после чтения, то при записи 0D не просто появляется перед 0A, а затирает собой стоящий перед 0A байт!

Автор: Свят86 30.8.2012, 10:35
вобщем я испробовал все комбинации fread fwrite, handle read write,  в различных режимах и чтения и записи и везде такой косяк... но по подсказке
вариант с fstream дал то что нужно! причем в буфере 0D есть, а при записи его уже нет! с буфера его убрать уже не проблема! smile конструкция получилась такая:
Код

#include <iostream>
#include <fstream>
#include <sys\stat.h>
using namespace std;
char *bytef; 
 
 int main()
{
    int length;
    struct stat statbuf;
    stat(path.c_str(),&statbuf);
    bytef=new char[statbuf.st_size];   \\в примере размер файла 369 байт

    fstream f(path.c_str(), ios::in | ios::binary);
    fstream fw("rez.txt", ios::out | ios::binary);
    
    f.read(bytef, statbuf.st_size);
    length=strlen(bytef);     \\после чтения bytef стал 374 байта (+5 0D)
    fw.write(bytef, statbuf.st_size);    \\записал 369 байт и получилась копия path.c_str() без 0D

    f.close();
    fw.close();
    
    return 0;
}
 

Автор: xvr 30.8.2012, 12:31
Покажите код, как вы писали этот файл

Автор: Свят86 30.8.2012, 16:21
исходник на другой машине и его я уже переделал! использовал fwrite   и write  в handle  оба варианта открывали файл для битового ввода!
 если использовать fstream то проблема уходит! пишется без добавления 0D! smile

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)