2011-08-16 7 views
1

私はJ#で書かれたパックファイルメソッドを持っています。これは、たくさんのファイルをストリームにまとめ、関連する 'unpack'メソッドで個々のファイルとして再構築できる十分なメタデータとともに書き出します。私は、この質問の最後に、J#が何をしているのかを示す良い兆候を示す、大まかなバージョンを提供しました。これを取得するには、.NETリフレクタをJ#コードで実行して同等のJ#ライブラリを生成します。明らかにロックされたファイルからFileStreamが0バイトを読み込む原因は何ですか?

今、以下のコードは、開発効率向上に完璧に動作しますが、断続的に生産にエラーが発生します。以下の「エラー1」と「エラー2」のコメントには、野生の両方で表示されている例外が表示されています。 「ERROR 2」が発生した場合、常に0バイトが書き込まれます。これらのエラーが発生した場合、明らかなパターンはありません。ファイルサイズは通常100kb未満です。

「パック」メソッドに渡されるファイルは非常に最近、前のミリ秒単位のように、壁時計時間を作成されています。出力ストリームは、共有なしで新しく作成されたファイルを指します。

だから時々私は私が存在している...私はちょうどそれを作成したので、知っているファイルに対して返される「0」のファイル長を取得し、要約します。 J#の関与のために、私は実際の例外を得ることができません。 (もちろん、私がデバッグしていた場合は、最初のチャンス例外を打ち破ることができますが、これは開発環境では決して起こらないと言われています)。それ以外のときは、ファイルが正常に開かれたにもかかわらず、そのファイルからバイトを読み取ることができません。コピープロセス中に例外がありますが、私は 'Read'が-1を返したと仮定することしかできません。

ここで何が起こっている可能性がありますか?何か案は?私の疑念は、Prodで実行されているが、devではないことがチェックされているウイルスであり、何とかそれが関係している可能性があります。しかし、ファイルを開いてロックして(WriteToStreamメソッドのように)、エラーなしで読み込みを停止させると、ウイルスチェッカーが何をすることができますか?私は、任意のファイルをロックすることができます少しテストアプリケーションを書いている...しかし、別のプロセスからファイルをロックするFileInfo.Lengthを停止していないように見えるし、ファイルストリームが開くと、あなたが望むように、

私は困惑しています。

編集:

OK - ここではJ#コードがあります。その質問には再タグ付けしました。

EDIT 2:

は、私はまた、長さ0のチェックは、トラブルシューティングの目的のために、後に追加されたことを言及する必要があります。これに先立って、「長さ」と「書かれた」を比較した後は常に失敗していました。 'length'が 'written'と等しくないときは、 'length'が0で、時には 'written'が0になることがあります。問題は自分のコードのバグではありませんが、この質問の目的は、私が記述した方法でコードが失敗する原因となる別のプロセス(ウイルスチェッカーなど)がこれらのファイルに対して実行できる処理を調べることです。

public static void packContentsToStream(Serializable serializable, Stream stream) 
{ 
    try 
    { 
     OutputStream output = new StreamWrapperOutputStream(stream); 

     FileRecordPair[] recordPairs = SerializationUtil.getRecords(serializable); 
     FileRecord[] records = new FileRecord[recordPairs.length]; 
     File[] files = new Files[recordPairs.length]; 

     for (int i = 0; i < recordPairs.length; i++) 
     { 
      FileRecordPair pair = recordPairs[i]; 
      records[i] = pair.getRecord(); 
      files[i] = pair.getFile(); 
     } 

     SerializationUtil.writeToStream(serializable, output, false); // False keeps stream open 
     SerializationUtil.writeToStream(records, output, false); 

     for (int i = 0; i < files.length; i++) 
     { 
      File file = files[i]; 
      long written = writeToStream(file, output); 
      if (written != records[i].getFileLength()) 
      { 
       throw new SystemException("Invalid record. The number of bytes written [" + written + "] did not match the recorded file length [" + records[i].getFileLength() + "]."); // ERROR 2 
      } 
     } 
    } 
    catch (Exception e) 
    { 
     throw new SystemException("Could not write FileRecords", e); 
    } 
} 


public static long writeToStream(HapiFile file, OutputStream stream) 
{ 
    long written = 0; 
    if (file.exists()) 
    { 
     FileInputStream fis = null; 
     try 
     { 
      fis = new FileInputStream(file); 
      written = copy(fis, stream); 
     } 
     catch (Exception e) 
     { 
      throw new SystemException("Could not write file to stream", e); 
     } 
     finally 
     { 
      if (fis != null) 
      { 
       try 
       { 
        fis.close(); 
       } 
       catch (IOException ioe) 
       { 
        // For now - throw an exception to see if this might be causing the packing error 
        throw new SystemException("Error closing file", ioe); 
       } 
      } 
     } 
    } 

    return written; 
} 

public static int copy(InputStream is, OutputStream stream) throws IOException 
{ 
    int total = 0; 
    int read = 0; 
    byte[] buffer = new byte[BUFFER_SIZE]; 

    while (read > -1) 
    { 
     read = is.read(buffer); 
     if (read > 0) 
     { 
      stream.write(buffer, 0, read); 
      total += read; 
     } 
    } 

    return total; 
} 

// Relevant part of 'SerializationUtil.getRecords' 

private static FileRecord GetFor(File file, String recordName, int index, String pathToInstance) 
{ 
    String fileName = file.getName(); 
    int length = (int) file.length(); // Safe as long as file is under 2GB 

    if (length == 0) 
    { 
     throw new SystemException("Could not obtain file length for '" + file.getPath() + "'"); // ERROR 1 
    } 

    if (index > -1 && recordName != null && recordName.length() > 0) 
    { 
     recordName = recordName + "." + index; 
    } 

    return new FileRecord(fileName, length, recordName, pathToInstance); 
} 

// File.length() implementation - obtained using .NET Reflector 
public virtual long length() 
{ 
    long length = 0L; 
    if (this.__fileInfo != null) 
    { 
     SecurityManager manager = System.getSecurityManager(); 
     if (manager != null) 
     { 
      manager.checkRead(this.__mCanonicalPath); 
     } 
     try 
     { 
      this.__fileInfo.Refresh(); 
      if (!this.exists() || !(this.__fileInfo is FileInfo)) 
      { 
       return 0L; 
      } 
      length = ((FileInfo) this.__fileInfo).Length; 
     } 
     catch (FileNotFoundException) 
     { 
     } 
     catch (IOException) 
     { 
     } 
    } 
    return length; 
} 
+0

コードは意味をなさない。'List 'には 'Add(x、y)'メソッドはありません。 – leppie

+0

また、 'WriteToStream'を呼び出す際にパラメータが間違っていると思われます。 – leppie

+0

'file'パラメータは' WriteToStream'でも使われていません。 – leppie

答えて

0

WriteToStreamメソッド。最初にファイルを閉じてください。常にそこにブロックを使用してください。

+0

J#コードがC#にしていることを「翻訳」している間は、それはちょっとタイプミスでした。私はコード例を明確にするよう修正しましたが、実際のコードでは、FileStreamを開く前に自分のプロセス内でファイルが開かず、後で閉じられます。 – sger6218

+0

私は起こっているかもしれないと思いますが、あなたのJ#コードが開かれていて、ワード上のN個のファイルのうちの5番目のファイルを想定することができます。しかし、あなたは最初からN番目までのファイルを処理する(長さを取得する)ようになりました。 – Zenwalker

+0

FWIWでは、ファイルレコード配列には常に0または1のファイルがあります。私たちの現在のコードベースは、実際には複数のファイルを持つものを実際にパックしようとはしません。 – sger6218

0

気にしないで... J#コードを呼び出したC#コードでの目的の1つは、J#コードはあてにファイルを削除したファイナライザを持っていました。 J#コードは問題ありませんでした。ウイルスチェッカーは責任を負いませんでした。私たちはちょうどその階級にサボテールを持っていた。ガベージコレクタが入ってきて、まだというメッセージが表示され、と表示されていました。

関連する問題