Попытка прочитать весь текстовый файл

Я пытаюсь прочитать все содержимое TXT-файла, не построчно, а все содержимое

и распечатать его на экране внутри текстового поля в xcode

я использую смесь obj-c и c ++ lang:

while(fgets(buff, sizeof(buff), in)!=NULL){
cout << buff;  // this print the whole output in the consoleNSString * string = [ NSString stringWithUTF8String:buff ] ;

[Data setStringValue:string]; // but this line only print last line inside the textfield instead of printing it all
}

Я пытаюсь распечатать все содержимое файла, как:

  1. что-то…
  2. что-то…
  3. так далее…

но вместо этого он просто печатает последнюю строку в текстовое поле, пожалуйста, помогите мне

1

Решение

Есть ли причина, по которой вы не используете Obj-C для чтения файла? Это было бы так просто, как:

NSData *d = [NSData dataWithContentsOfFile:filename];
NSString *s = [[[NSString alloc] initWithData:d encoding:NSUTF8StringEncoding] autorelease];
[Data setStringValue:s];

Изменить: Чтобы использовать код, который у вас есть сейчас, я бы попробовал что-то вроде этого:

while(fgets(buff, sizeof(buff), in)!=NULL){
NSMutableString *s = [[Data stringValue] mutableCopy];
[s appendString:[NSString stringWithUTF8String:buff]];
[Data setStringValue:s];
}
2

Другие решения

Прочитать файл, вернуть содержимое в виде строки C ++:

  // open the file
std::ifstream is;
is.open(fn.c_str(), std::ios::binary);

// put the content in a C++ string
std::string str((std::istreambuf_iterator<char>(is)),
std::istreambuf_iterator<char>());

В вашем коде вы используете C api (FILE* из cstdio). В C код более сложный:

char * buffer = 0; // to be filled with the entire content of the file
long length;
FILE * f = fopen (filename, "rb");

if (f) // if the file was correctly opened
{
fseek (f, 0, SEEK_END);  // seek to the end
length = ftell (f);      // get the length of the file
fseek (f, 0, SEEK_SET);  // seek back to the beginning
buffer = malloc (length); // allocate a buffer of the correct size
if (buffer)               // if allocation succeed
{
fread (buffer, 1, length, f);  // read 'length' octets
}
fclose (f); // close the file
}
1

Чтобы ответить на вопрос Зачем Ваше решение не сработало:

[Data setStringValue:string]; // but this line only print last line inside the textfield instead of printing it all

При условии, что Data относится к текстовому полю, setStringValue: заменяет все содержимое поля на строку, которую вы передали. Ваш цикл читает и устанавливает одну строку за раз, поэтому в любой момент времени, string это одна строка из файла.

Представления должны отображаться только тогда, когда вы ничего не делаете в главном потоке, поэтому ваш цикл — при условии, что вы не запускали его в другом потоке или очереди — не печатает по одной строке за раз. Вы читаете каждую строку и заменяете содержимое текстового поля этой строкой, поэтому, когда ваш цикл заканчивается, поле остается с последним, что вы установили его stringValue до — последняя строка из файла.

Хлопать весь файл сразу будет работать, но пара проблем остается:

  • Текстовые поля не предназначены для отображения нескольких строк. Независимо от того, как вы читаете файл, вы все равно помещаете его содержимое в место, не предназначенное для такого содержимого.
  • Если файл достаточно большой, его чтение займет значительное время. Если вы сделаете это в главном потоке, то в течение этого времени приложение будет зависать.

Правильное решение будет:

  1. Используйте текстовое представление, а не текстовое поле. Текстовые представления созданы для работы с текстом любого количества строк, и когда вы создаете его в кончике, он бесплатно добавляется в представление прокрутки.
  2. Читайте файл по одной строке или другому фрагменту ограниченного размера за раз, но не в for или же while петля. Используйте NSFileHandle или dispatch_sourceлюбой из которых будет вызывать блок, который вы предоставляете, когда они читают другой фрагмент файла.
  3. Добавьте каждый блок в хранилище текстового представления вместо замены всего текста им.
  4. Показать индикатор прогресса, когда вы начинаете читать, а затем скрыть его, когда вы закончите чтение. Для дополнительного кредита, сделайте это определенным индикатором выполнения, показывая пользователю, как далеко вы прошли через файл.
0