2015-05-27 4 views
0

Я уже пытался прочитать файл в TFileStream, но вот где я застрял, файл вставлен в TFileStream, но я не могу прочитайте байты файла, я не запрограммировал это время, пожалуйста, помогите мне.Необходимо прочитать файл любого расширения по одному байту за один раз XE5 в динамический массив

Я также попытался прочитать его в обычный файл

var 
    myFile : File; 
    byteArray : array of byte; 
    oneByte : byte; 
    i, count : Integer; 

begin 
    // Try to open the Test.byt file for writing to 
    AssignFile(myFile, 'C:\Users\theunie\Desktop\Toets\Test2.txt'); 

    // Reopen the file for reading only 
    FileMode := fmOpenRead; 
    Reset(myFile, 1); // Now we define one record as 1 byte 

    // Display the file contents 
    // Start with a read of the first 6 bytes. 'count' is set to the 
    // actual number read 
    ShowMessage('Reading first set of bytes :'); 
    setlength(ByteArray,sizeof(myfile)); 
    BlockRead(myFile, byteArray, sizeof(myFile), count); 

    // Display the byte values read 
    for i := 0 to count do 
    ShowMessage(IntToStr(byteArray[i])); 

    // Now read one byte at a time to the end of the file 
    ShowMessage('Reading remaining bytes :'); 
    while not Eof(myFile) do 
    begin 
    BlockRead(myFile, oneByte, 1); // Read and display one byte at a time 
    ShowMessage(IntToStr(oneByte)); 
    end; 
    Freeandnil(byteArray); 
    // Close the file for the last time 
    CloseFile(myFile); 
end; 

, а также этой

procedure TForm1.Button1Click(Sender: TObject); 
var 
tf : TFileStream; //My Filestream 
ar : array of byte;//The dynamic array I want to read it into 
k : integer;//count 
s : string;//I want to display this at the end 
begin 
k := 0; 
tf := TFileStream.Create('C:\Users\Theunie\Desktop\Test2.txt',fmOpenReadwrite); 
try 
    inc(k); 
    SetLength(ar,k); 
    ar[k-1] := tf.Read(ar[k-1],tf.size); 
finally 
s := inttostr(ar[0]) +';'; 
for k := 1 to length(ar) do 
begin 
    s := s + ';' + IntToStr(ar[k]); 
end; 
FreeAndNil(ar); 
end; 
RichEdit1.Lines.Add(s); 
end; 
+2

'SetLength (ByteArray, sizeof (myfile)); ': function' sizeof (myfile) 'возвращает не размер файла, а размер переменной' myfile'. – Abelisto

+0

Вам не нужно читать в массив dyn.Вам нужна строка с разделителями, поэтому нет необходимости в массиве. Почему вы просите написать файл, когда вы только читаете его. –

ответ

1

является файл большой? Может ли он вписаться в оперативную память сразу?

У вас в основном есть две простые опции для создания DynArray из файла, но они рекомендуются только для файлов с малыми и средними значениями.

1: http://www.freepascal.org/docs-html/rtl/classes/tbytesstream.html

var BS: TBytesStream; b: byte; L, i: integer; 
begin 
    BS := TBytesStream.Create; 
    try 
    BS.LoadFromFile('c:\boot.ini'); 
    L := High(BS.Bytes); 
    for i := 0 to L do begin 
     b := BS.Bytes[i]; 
     ShowMessage(IntToStr(b)); 
    end; 
    finally 
    BS.Destroy; 
    end; 
end; 

2: использование IOUtils классы

и так далее

var BS: TBytes; b: byte; L, i: integer; 
begin 
    BS := TFile.ReadAllBytes('c:\boot.ini'); 
    L := High(BS); 
    for i := 0 to L do begin 
    b := BS[i]; 
    ShowMessage(IntToStr(b)); 
    end; 
end; 

С другой стороны, чтобы сохранить содержимое массива в файл, который вы бы использовать что-то вроде How to convert TBytes to Binary File? (using MemoryStream)


Что касается ваших попыток.

http://wiki.freepascal.org/File_Handling_In_Pascal

  1. , как это уже было отмечено выше, SizeOf не имеет никакого отношения к файлам, то есть размер памяти переменного типа File. Если вы хотите придерживаться старого API TurboPascal, вам необходимо использовать функцию FileSize, чтобы установить размер сразу. Для небольших файлов это будет хорошо, для больших файлов сам подход «сразу же считывает все данные в память, а затем обрабатывает».

  2. inc(k); SetLength(ar,k); - в цикле +1 - это очень плохая идея, это означает фрагментацию кучи и копирование и повторное копирование и повторное копирование буфера данных gorwing. То есть Length*Length/2 масштабирование, а также может быть сильно повреждающей структурой памяти кучи (google около heap fragmentation).
    Когда вы можете - вам нужно, прежде чем проверить FileSize в и установить массив

  3. FreeAndNil(byteArray); - совершенно неправильно. Массивы не являются объектами. Вы не можете использовать Destroy/Free/FreeAndNil над ними. Как очистить динарму? Ну, вы можете просто ничего не делать, поскольку dynarrays - это один из типов с автоподтверждением, например, строки и интерфейсы и т. Д.Пока ваша процедура завершается, Delphi автоматически освобождает память от локальных переменных. Однако, если вы хотите, чтобы очистить dynarray в середине процедуры вы можете сделать это с помощью SetLength(MyDynArray, 0) или ярлык MyDynArray := nil

  4. BlockRead(myFile, byteArray, sizeof(myFile), count) является неправильным на злоупотребления SizeOf. Но у него есть и другая ошибка: ByteArray переменная - это в основном указатель, поэтому это всего 4 (четыре!) Байта (8 байтов в коде Win64), поэтому вы просто перезаписываете весь стек вызовов. Вы действительно должны лучше использовать современный API-интерфейс типа. Но если вы хотите придерживаться старого небезопасного низкоуровневого API, тогда вам нужно быть предельно ясным на низкоуровневой реализации переменных разных типов. В основном вы хотите прочитать содержимое файла не в указатель на буфер, а в буфер, на который указывает, поэтому он должен быть как BlockRead(myFile, byteArray[0], MyFileAndArraySize, count). Затем, если была прочитана только часть вашего файла - count < MyFileAndArraySize - вы бы BlockRead(myFile, byteArray[count], MyFileAndArraySize - count, count1), затем BlockRead(myFile, byteArray[count+count1], MyFileAndArraySize - count - count1, count2) и так далее. Заботливо, даже если вы понимаете, как байты работают в низкоуровневых типах ...

  5. ar[k-1] := tf.Read(ar[k-1],tf.size); - это просто ужасно. Проверьте http://www.freepascal.org/docs-html/rtl/classes/tstream.read.html - результат - сколько байтов было действительно прочитано. Поэтому вместо заполнения массива содержимым файла вы чувствуете, что «сколько байтов было прочитано в одной попытке?» вместо. Вместо этого вы должны использовать процедуру tf.ReadBuffer.

Но если вы хотите идти через части tf.Read это должно быть что-то вроде

k := 0; 
SetLength(ar, tf.Size); 
while k < tf.Size do begin 
    k := k + tf.Read(ar[k], tfSize - k); 
end; 

Но опять же, у вас есть гораздо более простые инструменты для работы с небольшими файлами в современной Delphi


Еще одна проблема в вашем коде находится в

s := inttostr(ar[0]) +';'; 
for k := 1 to length(ar) do 
begin 
    s := s + ';' + IntToStr(ar[k]); 
end; 

Это так называемая «разовая ошибка».

Хотя строки по историческим причинам индексируются от 1 до Length(s) и обычно не имеют 0-го элемента, динамиков нет.

Динамические массивы индексируются от 0 = Low(ArrayVarName) до High(ArrayVarName) = Length(ArrayVarName) - 1. Таким образом, ваша петля пытается прочитать память за концом массива, вне самого массива.

Другая ошибка в том, что вы начинаете его с двумя точками с запятой, например «10 ;; 20; 30; 40 .....»

Это типично, когда вы устали или не очень внимателен. Поэтому вам лучше избегать индексирования массивов. Ниже рабочий код для включения динамического массива в строку из Delphi XE2

procedure TForm1.Button1Click(Sender: TObject); 
var DynamicArray: TBytes; 
    SB: TStringBuilder; iSL: IJclStringList; 
    s1,s2: string; b: byte; 
begin 
    DynamicArray := TBytes.Create(10, 20, 30, 40, 50); 

    SB := TStringBuilder.Create; 
    try 
    for b in DynamicArray do begin 
     if SB.Length > 0 then 
      SB.Append(';'); 
     SB.Append(b); 
    end; 

    s1 := SB.ToString; 
    finally 
    SB.Destroy; // you must do it in Delphi for Windows 
    end; 

    iSL := JclStringList(); 
    for b in DynamicArray do 
    iSL.Add(IntToStr(b)); 
    s2 := iSL.Join(';'); 
    iSL := nil; // you may skip it, Delphi would do on exit from procedure 

    ShowMessage('Dynamic array of bytes to string' 
       + ^M^J' with Delphi RTL: ' + s1 
       + ^M^J' with J.E.D.I. Code Library: ' + s2); 

end; 

Немного больше о динамических массивов:

+0

Файл большой, но большое спасибо. – theunie

+1

Я не понимаю этот комментарий. Вы решили, что хотите прочитать весь файл в памяти. Более того, вы создаете строку, которая намного больше. Я не думаю, что вы понимаете ответ, представленный здесь. –

+1

@DavidHeffernan Я считаю, что это был не тот вопрос, который я неправильно понял, но теперь я понимаю, что все ответили на мой вопрос и прокомментировали это. Я очень благодарен. – theunie

 Смежные вопросы

  • Нет связанных вопросов^_^