2011-01-17 9 views
1

私は学校の割り当てを受けて、jpgイメージを送信し、100バイトのグループに分割し、破損し、CRCチェックを使用してエラーを特定し、最終的にその原形。Javaイメージ転送の問題

新しい画像をチェックアウトすると、実際には準備が整いましたが、エラーが表示されます。

誰かが以下の私のコードを見て、私はすべてがOKに見えるため、問題が何であるかを理解することはできませんとして多分この論理的間違いを見つけることができれば、私は本当に感謝

:S

必要なすべてのデータを含むファイルについて写真やエラーパターンなど、このリンクからダウンロードできます:http://rapidshare.com/#!ダウンロード| 932tl2 | 443122762 | Data.zip | 739

コード内のパスを変更するのを忘れないでくださいイメージファイルとエラーファイル用。私はあなたがそれに近づくことができる方法を説明します以下の手順に従って終わると同じようにデバッグする方法を学ぶ

package networks; 

import java.io.*;    // for file reader 
import java.util.zip.CRC32;  // CRC32 IEEE (Ethernet) 

public class Main { 

/** 
* Reads a whole file into an array of bytes. 
* @param file The file in question. 
* @return Array of bytes containing file data. 
* @throws IOException Message contains why it failed. 
*/ 
public static byte[] readFileArray(File file) throws IOException { 
    InputStream is = new FileInputStream(file); 
    byte[] data=new byte[(int)file.length()]; 
    is.read(data); 
    is.close(); 
    return data; 
} 

/** 
* Writes (or overwrites if exists) a file with data from an array of bytes. 
* @param file The file in question. 
* @param data Array of bytes containing the new file data. 
* @throws IOException Message contains why it failed. 
*/ 
public static void writeFileArray(File file, byte[] data) throws IOException { 
    OutputStream os = new FileOutputStream(file,false); 
    os.write(data); 
    os.close(); 
} 

/** 
* Converts a long value to an array of bytes. 
* @param data The target variable. 
* @return Byte array conversion of data. 
* @see http://www.daniweb.com/code/snippet216874.html 
*/ 
public static byte[] toByta(long data) { 
    return new byte[] { 
     (byte)((data >> 56) & 0xff), 
     (byte)((data >> 48) & 0xff), 
     (byte)((data >> 40) & 0xff), 
     (byte)((data >> 32) & 0xff), 
     (byte)((data >> 24) & 0xff), 
     (byte)((data >> 16) & 0xff), 
     (byte)((data >> 8) & 0xff), 
     (byte)((data >> 0) & 0xff), 
    }; 
} 

/** 
* Converts a an array of bytes to long value. 
* @param data The target variable. 
* @return Long value conversion of data. 
* @see http://www.daniweb.com/code/snippet216874.html 
*/ 
public static long toLong(byte[] data) { 
    if (data == null || data.length != 8) return 0x0; 
    return (long)(
     // (Below) convert to longs before shift because digits 
     // are lost with ints beyond the 32-bit limit 
     (long)(0xff & data[0]) << 56 | 
     (long)(0xff & data[1]) << 48 | 
     (long)(0xff & data[2]) << 40 | 
     (long)(0xff & data[3]) << 32 | 
     (long)(0xff & data[4]) << 24 | 
     (long)(0xff & data[5]) << 16 | 
     (long)(0xff & data[6]) << 8 | 
     (long)(0xff & data[7]) << 0 
    ); 
} 

public static byte[] nextNoise(){ 
    byte[] result=new byte[100]; 
    // copy a frame's worth of data (or remaining data if it is less than frame length) 
    int read=Math.min(err_data.length-err_pstn, 100); 
    System.arraycopy(err_data, err_pstn, result, 0, read); 
    // if read data is less than frame length, reset position and add remaining data 
    if(read<100){ 
     err_pstn=100-read; 
     System.arraycopy(err_data, 0, result, read, err_pstn); 
    }else // otherwise, increase position 
     err_pstn+=100; 
    // return noise segment 
    return result; 
} 

/** 
* Given some original data, it is purposefully corrupted according to a 
* second data array (which is read from a file). In pseudocode: 
* corrupt = original xor corruptor 
* @param data The original data. 
* @return The new (corrupted) data. 
*/ 
public static byte[] corruptData(byte[] data){ 
    // get the next noise sequence 
    byte[] noise = nextNoise(); 
    // finally, xor data with noise and return result 
    for(int i=0; i<100; i++)data[i]^=noise[i]; 
    return data; 
} 

/** 
* Given an array of data, a packet is created. In pseudocode: 
* frame = corrupt(data) + crc(data) 
* @param data The original frame data. 
* @return The resulting frame data. 
*/ 
public static byte[] buildFrame(byte[] data){ 
    // pack = [data]+crc32([data]) 
    byte[] hash = new byte[8]; 
    // calculate crc32 of data and copy it to byte array 
    CRC32 crc = new CRC32(); 
    crc.update(data); 
    hash=toByta(crc.getValue()); 
    // create a byte array holding the final packet 
    byte[] pack = new byte[data.length+hash.length]; 
    // create the corrupted data 
    byte[] crpt = new byte[data.length]; 
    crpt = corruptData(data); 
    // copy corrupted data into pack 
    System.arraycopy(crpt, 0, pack, 0, crpt.length); 
    // copy hash into pack 
    System.arraycopy(hash, 0, pack, data.length, hash.length); 
    // return pack 
    return pack; 
} 

/** 
* Verifies frame contents. 
* @param frame The frame data (data+crc32). 
* @return True if frame is valid, false otherwise. 
*/ 
public static boolean verifyFrame(byte[] frame){ 
    // allocate hash and data variables 
    byte[] hash=new byte[8]; 
    byte[] data=new byte[frame.length-hash.length]; 
    // read frame into hash and data variables 
    System.arraycopy(frame, frame.length-hash.length, hash, 0, hash.length); 
    System.arraycopy(frame, 0, data, 0, frame.length-hash.length); 
    // get crc32 of data 
    CRC32 crc = new CRC32(); 
    crc.update(data); 
    // compare crc32 of data with crc32 of frame 
    return crc.getValue()==toLong(hash); 
} 

/** 
* Transfers a file through a channel in frames and reconstructs it into a new file. 
* @param jpg_file File name of target file to transfer. 
* @param err_file The channel noise file used to simulate corruption. 
* @param out_file The name of the newly-created file. 
* @throws IOException 
*/ 
public static void transferFile(String jpg_file, String err_file, String out_file) throws IOException { 
    // read file data into global variables 
    jpg_data = readFileArray(new File(jpg_file)); 
    err_data = readFileArray(new File(err_file)); 
    err_pstn = 0; 
    // variable that will hold the final (transfered) data 
    byte[] out_data = new byte[jpg_data.length]; 
    // holds the current frame data 
    byte[] frame_orig = new byte[100]; 
    byte[] frame_sent = new byte[100]; 
    // send file in chunks (frames) of 100 bytes 
    for(int i=0; i<Math.ceil(jpg_data.length/100); i++){ 
     // copy jpg data into frame and init first-time switch 
     System.arraycopy(jpg_data, i*100, frame_orig, 0, 100); 
     boolean not_first=false; 
     System.out.print("Packet #"+i+": "); 
     // repeat getting same frame until frame crc matches with frame content 
     do { 
      if(not_first)System.out.print("F"); 
      frame_sent=buildFrame(frame_orig); 
      not_first=true; 
     }while(!verifyFrame(frame_sent)); // usually, you'd constrain this by time to prevent infinite loops (in 
              // case the channel is so wacked up it doesn't get a single packet right) 
     // copy frame to image file 
     System.out.println("S"); 
     System.arraycopy(frame_sent, 0, out_data, i*100, 100); 
    } 
    System.out.println("\nDone."); 
    writeFileArray(new File(out_file),out_data); 
} 

// global variables for file data and pointer 
public static byte[] jpg_data; 
public static byte[] err_data; 
public static int err_pstn=0; 

public static void main(String[] args) throws IOException { 

    // list of jpg files 
    String[] jpg_file={ 
     "C:\\Users\\Stefan\\Desktop\\Data\\Images\\photo1.jpg", 
     "C:\\Users\\Stefan\\Desktop\\Data\\Images\\photo2.jpg", 
     "C:\\Users\\Stefan\\Desktop\\Data\\Images\\photo3.jpg", 
     "C:\\Users\\Stefan\\Desktop\\Data\\Images\\photo4.jpg" 
    }; 

    // list of error patterns 
    String[] err_file={ 
     "C:\\Users\\Stefan\\Desktop\\Data\\Error Pattern\\Error Pattern 1.DAT", 
     "C:\\Users\\Stefan\\Desktop\\Data\\Error Pattern\\Error Pattern 2.DAT", 
     "C:\\Users\\Stefan\\Desktop\\Data\\Error Pattern\\Error Pattern 3.DAT", 
     "C:\\Users\\Stefan\\Desktop\\Data\\Error Pattern\\Error Pattern 4.DAT" 
    }; 
    // loop through all jpg/channel combinations and run tests 
    for(int x=0; x<jpg_file.length; x++){ 
     for(int y=0; y<err_file.length; y++){ 
      System.out.println("Transfering photo"+(x+1)+".jpg using Pattern "+(y+1)+"..."); 
      transferFile(jpg_file[x],err_file[y],jpg_file[x].replace("photo","CH#"+y+"_photo")); 
     } 
    } 

} 

}

答えて

1

は、おそらく開発のための最も重要な教訓の一つである、そう。

  1. プログラムの単体テストを行います。
  2. あなたはそれを100バイトの チャンクに対してハードコーディングしました。あなたの ユニットテストが (おそらく5または10)に値を変更できるように、その変数を作ります。
  3. 最初のテストでは、既知のバイトチャンクを使用します。
  4. 破損している可能性があります。 が破損していることを確認してください。 そうでない場合は、修正してください。
  5. 次に、 が送信されたものが であったことを確認して送信をテストします。
  6. 次に、固定をテストします。
  7. 次に、大きいサイズの (おそらく20)、次に100、次に イメージで行います。

サイズがハードコードされていることは悪い習慣です。単体テストのないコードを書くことは悪いです。テストすることができないコードを書くことができるので、デバッグするのが難しくなります。

これにより、期待どおりに機能していない関数を見つけることができ、何が起こっているのかを判断できます。コードをリファクタリングし、関数を小さな単位に分割する必要があります。

関連する問題