2011-01-17 1 views
1

J'ai une tâche d'école, pour envoyer une image jpg, la diviser en groupes de 100 octets, la corrompre, utiliser une vérification CRC pour localiser les erreurs et retransmettre jusqu'à ce qu'elle soit finalement intégrée dans son forme originale.Problème de transfert d'image Java

Il est pratiquement prêt, mais quand je regarde les nouvelles images, elles apparaissent avec des erreurs.

J'apprécierais vraiment si quelqu'un pourrait regarder mon code ci-dessous et trouvez peut-être cette erreur logique que je ne comprends pas ce que le problème est que tout est ok: S

Pour le fichier avec toutes les données nécessaires y compris les photos et les modèles d'erreur on pourrait le télécharger à partir de ce lien: http: //rapidshare.com/#! télécharger | 932tl2 | 443122762 | Data.zip | 739

N'oubliez pas de changer les chemins dans le code pour les fichiers d'image et d'erreur.

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")); 
     } 
    } 

} 

}

Répondre

1

Apprendre à déboguer est probablement l'une des leçons les plus importantes pour le développement, donc, que je finirais suivant ces étapes, je vais décrire comment vous pouvez l'aborder.

  1. Faites un test unitaire pour votre programme.
  2. Vous l'avez codé en dur pour des blocs de 100 octets. Faites cette variable, donc votre test unitaire peut changer la valeur, à peut-être 5 ou 10 au début.
  3. Votre premier test consiste à prendre un bloc d'octets connu de .
  4. Il sera corrompu, vérifiez que la corruption est ce qui était attendu. Si non, corrigez-le.
  5. Ensuite, tester la transmission, vérifier que ce qui a été transmis est ce qui a été reçu.
  6. Ensuite, testez la fixation.
  7. Puis le faire avec une plus grande taille, peut-être 20, puis faire 100, puis une image .

Avoir la taille codée en dur est une mauvaise pratique. L'écriture de code sans tests unitaires est mauvaise, car vous pouvez écrire le code qui n'est pas testable, donc il est plus difficile à déboguer. Cela vous permettra de trouver quelles fonctions ne fonctionnent pas selon vos attentes, et vous pourrez déterminer ce qui se passe, vous devrez peut-être refactoriser votre code et diviser les fonctions en unités plus petites.