2015-03-14 6 views
-1

Я написал код клиента/сервера, который перемещает файлы взад и вперед между системами через Delphi, написанный WebService. Из-за ограничений шлюзов перед службой мне пришлось разделить большие файлы на несколько сообщений. Приведенный ниже код часто работает в моем тестировании. Иногда, однако, на последнем фрагменте данных, похоже, он не попадает в результирующий файл. У меня есть еще одна версия кода, где я добавил подробный журнал на каждом шагу, чтобы проверить текущую позицию в FileStream до и после вызовов writeBuffer и получить размер промежуточного файла. Кажется, что эта версия кода работает каждый раз, и это заставляет меня думать, что я могу столкнуться с какой-то проблемой времени. Должен ли я делать Flush на Stream после каждой записи или чего-то подобного?Созданный файл TFileStream отсутствовал.

 responseObj := DocSvc.getDocument(GetFileInHeader, GetFileIn); 
      while processingGetFile do 
      begin 
        chunkID := StrToInt(responseObj.ValidationResults[0].ValidationResultId); 

        if chunkID = -3 then 
        begin 
          processingGetFile := false; 
          break; 
        end; 
        if chunkID = -2 then 
        begin 
          if responseObj.opsResponseobj.status then 
          begin 
            if responseObj.opsResponseObj.document <> 'NONEWFILE' then 
            begin 
              if FileExists2(DesintationFilePath) then 
                DeleteFile(DesintationFilePath); 
              Zipfile := TFileStream.Create(DesintationFilePath,FmOpenReadWrite or FmShareDenyNone or fmCreate); 
              DecodedZipfile := DecodeString(responseObj.opsResponseobj.document); 
              Zipfile.WriteBuffer(Pointer(DecodedZipfile)^, length(DecodedZipfile)); 

              iniTransmit.WriteString(‘DocumentSection’,string(FileID), responseObj.ValidationResults[0].ReasonCode); 
              FreeAndNil(Zipfile); 
            end; 
            result := true; 
            processingGetFile := false; 
          end 
          else 
          begin 
          //Log failure 
          end; 
        end 
        else if chunkID = -1 then 
        begin 

          Zipfile.Position := getFileSize(DesintationFilePath); 
          DecodedZipfile := DecodeString(responseObj.opsResponseObj.document); 

          Zipfile.WriteBuffer(Pointer(DecodedZipfile)^, Length(DecodedZipfile)); 
  
          iniTransmit.WriteString(‘DocumentSection’,string(FileID), responseObj.ValidationResults[0].ReasonCode); 
          result := true; 
          processingGetFile := false; 
        end 
        else // in the middle of receiving pieces of a big file. Save off what we have, ask for more. 
        begin 
          if chunkID = 1 then 
          begin 
            if FileExists2(DesintationFilePath) then 
              DeleteFile(DesintationFilePath); 
            Zipfile := TFileStream.Create(DesintationFilePath,FmOpenReadWrite or FmShareDenyNone or fmCreate); 
          end; 

          Zipfile.Position := getFileSize(DesintationFilePath); 
          DecodedZipfile := DecodeString(responseObj.opsResponseObj.document); 

          Zipfile.WriteBuffer(Pointer(DecodedZipfile)^, Length(DecodedZipfile)); 

          GetFileInHeader.messageFlowSequence := chunkID; 
          responseObj := DocSvc.getDocument(GetFileInHeader, GetFileIn); 
        end; 
      end; 


function getFileSize(path: string): integer; 
var 
  info : TWin32FileAttributeData; 
begin 
  result := -1; 
  
  if not GetFileAttributesex(Pchar(path), GetFileExInfoStandard, @info) then 
    exit; 
  
  result := (info.nFileSizeLow or (info.nFileSizeHigh shl 32)); 
end; 
+0

Сложно прочитать код из-за дублирования. Используйте переменные, чтобы избежать повторения одной и той же строки. Разделение кода написания файла на отдельный метод помогло бы. Вам нужно использовать try/finally. 'info.nFileSizeHigh shl 32 = info.nFileSizeHigh'. Перед применением shl вам нужно отправить в Int64. –

+0

Это всего лишь отрывок из всей функции, она сидит в блоке try/except для обработки ошибок и блок try/finally для освобождения ресурсов. Когда возникает проблема не всех данных, поступающих в файл, никаких исключений не возникает. – mcmar

+0

В коде явно отсутствуют блоки. Во всяком случае, дублирование затрудняет чтение. Вы просите об ошибках. –

ответ

2

Ваш вопрос, кажется, вдоль линий, нужно ли делать больше, чем это, чтобы записать в файл:

Stream := TFileStream.Create(...); 
Try 
    Stream.WriteBuffer(...); 
Finally 
    Stream.Free; 
End; 

Ответ: нет. Не нужно ничего смывать.

Возможно, проблема связана с режимом совместного использования. Вы пошли за fmShareDenyNone. Это означает, что можно открыть несколько дескрипторов файлов, имеющих доступ на запись. Это означает, что вы открыты для гонок при записи файла.