Java图像传输问题

Java图像传输问题,java,image,networking,crc32,Java,Image,Networking,Crc32,我有一个学校作业,发送一个jpg图像,将它分成100字节的组,破坏它,使用CRC检查定位错误并重新传输,直到它最终被构建回原始形式 它实际上已经准备好了,但是当我查看新图像时,它们出现了错误 如果有人能看看我下面的代码,也许能找到这个逻辑错误,我会非常感激,因为我不明白问题是什么,因为一切看起来都很正常:S 对于包含所有所需数据(包括照片和错误模式)的文件,可以从以下链接下载:http://rapidshare.com/#!下载| 932tl2 | 443122762 | Data.zip |

我有一个学校作业,发送一个jpg图像,将它分成100字节的组,破坏它,使用CRC检查定位错误并重新传输,直到它最终被构建回原始形式

它实际上已经准备好了,但是当我查看新图像时,它们出现了错误

如果有人能看看我下面的代码,也许能找到这个逻辑错误,我会非常感激,因为我不明白问题是什么,因为一切看起来都很正常:S

对于包含所有所需数据(包括照片和错误模式)的文件,可以从以下链接下载:http://rapidshare.com/#!下载| 932tl2 | 443122762 | Data.zip | 739

不要忘记在代码中更改图像和错误文件的路径

封装网络;
导入java.io.*;//用于文件读取器
导入java.util.zip.CRC32;//CRC32 IEEE(以太网)
公共班机{
/**
*将整个文件读入字节数组。
*@param file正在讨论的文件。
*@返回包含文件数据的字节数组。
*@IOException消息包含失败的原因。
*/
公共静态字节[]readFileArray(文件)引发IOException{
InputStream is=新文件InputStream(文件);
字节[]数据=新字节[(int)file.length()];
is.读取(数据);
is.close();
返回数据;
}
/**
*使用字节数组中的数据写入(或覆盖,如果存在)文件。
*@param file正在讨论的文件。
*@param数据包含新文件数据的字节数组。
*@IOException消息包含失败的原因。
*/
公共静态void writeFileArray(文件,字节[]数据)引发IOException{
OutputStream os=新文件OutputStream(文件,false);
写(数据);
os.close();
}
/**
*将长值转换为字节数组。
*@param data指定目标变量。
*@返回数据的字节数组转换。
*@见http://www.daniweb.com/code/snippet216874.html
*/
公共静态字节[]toByta(长数据){
返回新字节[]{
(字节)((数据>>56)和0xff),
(字节)((数据>>48)和0xff),
(字节)((数据>>40)和0xff),
(字节)((数据>>32)和0xff),
(字节)((数据>>24)和0xff),
(字节)((数据>>16)和0xff),
(字节)((数据>>8)和0xff),
(字节)((数据>>0)和0xff),
};
}
/**
*将字节数组转换为长值。
*@param data指定目标变量。
*@返回数据的长值转换。
*@见http://www.daniweb.com/code/snippet216874.html
*/
公共静态长toLong(字节[]数据){
if(data==null | | data.length!=8)返回0x0;
返回(长)(
//(以下)在移位前转换为长,因为数字
//当整数超过32位限制时丢失

(long)(0xff&data[0])学习如何调试可能是开发过程中最重要的课程之一,因此,在我结束以下步骤时,我将介绍如何进行调试

  • 为你的程序做一个单元测试
  • 您将其硬编码为100字节 块。使这个变量,所以你的 单元测试可以将值更改为 一开始可能是5或10
  • 你的第一个测试是取一个已知的5 字节块
  • 它将被损坏,请验证 腐败是意料之中的事。 如果没有,请修复它
  • 然后测试传输,验证 传播的是过去的 收到
  • 然后测试固定
  • 然后用更大的尺寸做, 也许20个,然后做100个,然后一个 形象
  • 将大小硬编码是不好的做法。在没有单元测试的情况下编写代码是不好的,因为您可能(将)然后编写不可测试的代码,因此更难调试

    这将使您能够发现哪些函数没有按照您的期望工作,并且您可以确定发生了什么,您可能需要重构代码并将函数分解为更小的单元

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