读取或写入二进制文件有未知问题

问题描述

我正在用 Java 开发一个文件压缩器,它使用 .png 格式,每个像素都有代表 2 个字节或 1 个字节的不同颜色。但是不知何故压缩时的二进制文件有点偏离(它创建了一个 log.txt 文件来比较二进制文件)但它仍然可以很好地读取颜色,我创建了 2 个名为“SingleByteCodec.txt”和“DoubleByteCodec.txt”的文本文件,在每行中的 SingleByteCodec 有一个不同的字节和颜色,在 DoubleByteCodec 中每行有 2 个字节和一种颜色。当我压缩一个txt文件然后解压缩它是结果

原文:你好世界!!你今天过得好吗?

压缩和解压后:HellllWoWod!! !今天还在犹豫吗?

这是我的代码

主类:

    package image_to_png;
    
    import java.awt.FileDialog;
    import java.awt.FlowLayout;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.io.File;
    import java.io.IOException;
    import javax.swing.JButton;
    import javax.swing.JFrame;
    
    public class Main {
        
        static File inputFile;
        static int index = 0;
        static double percent = 0;
        static int percentBoost = 0;
        static StringBuilder log = new StringBuilder();
        
        
        
    
    
        public static void main(String[] args) {
            JFrame f = new JFrame("Uncompress or Compress");
            f.setDefaultCloSEOperation(JFrame.EXIT_ON_CLOSE);
            f.setBounds(500,200,500,500);
            JButton comp = new JButton("Compress");
            JButton uncomp = new JButton("Uncompress");
            f.setLayout(new FlowLayout());
            f.add(comp);
            f.add(uncomp);
            comp.addActionListener(new ActionListener(){
    
                @Override
                public void actionPerformed(ActionEvent e) {
                    JFrame f2 = new JFrame();
                    FileDialog fd = new FileDialog(f2,"select file to compress",FileDialog.LOAD);
                    fd.setVisible(true);
                    inputFile = new File(fd.getDirectory() + "\\" + fd.getFile());
                    JFrame f3 = new JFrame();
                    FileDialog fd2 = new FileDialog(f3,"select output file",FileDialog.SAVE);
                    fd2.setVisible(true);
                    File file2 = new File(fd2.getDirectory() + "\\" + fd2.getFile());
                    if (file2.exists()) {
                        
                    }else {
                        try {
                            file2.createNewFile();
                        } catch (IOException e1) {
                            // Todo Auto-generated catch block
                            e1.printstacktrace();
                        }
                    }
                    try {
                        Compress.compress(inputFile,file2);
                    } catch (IOException e1) {
                        // Todo Auto-generated catch block
                        e1.printstacktrace();
                    }
                    
                }
                
                    
                
            });
            uncomp.addActionListener(new ActionListener() {
    
                @Override
                public void actionPerformed(ActionEvent e) {
                    JFrame f2 = new JFrame();
                    FileDialog fd = new FileDialog(f2,"select file to uncompress",FileDialog.LOAD);
                    fd.setVisible(true);
                    File file = new File(fd.getDirectory() + "\\" + fd.getFile());
                    
                    JFrame f3 = new JFrame();
                    FileDialog fd2 = new FileDialog(f3,FileDialog.SAVE);
                    fd2.setVisible(true);
                    File file2 = new File(fd2.getDirectory() + "\\" + fd2.getFile());
                    if(file2.exists()) {
                        
                    }else {
                        try {
                            file2.createNewFile();
                        } catch (IOException e1) {
                            // Todo Auto-generated catch block
                            e1.printstacktrace();
                        }
                    }
                    try {
                        Uncompress.uncompress(file,file2);
                    } catch (IOException e1) {
                        // Todo Auto-generated catch block
                        e1.printstacktrace();
                    }
                    
                }
                
            });
            f.setVisible(true);
            
        }
    
        
        
        
        
        
        
        
        
        
    
        
        
        
        
    }

压缩类:

        package image_to_png;
        
        import java.awt.Color;
        import java.awt.image.BufferedImage;
        import java.io.BufferedInputStream;
        import java.io.File;
        import java.io.FileInputStream;
        import java.io.FileNotFoundException;
        import java.io.FileWriter;
        import java.io.IOException;
        import java.util.Scanner;
        
        import javax.imageio.ImageIO;
        
        public class Compress {
            static int arrayLength = 256;
            static int arrayLength2 = 51344;
            static Color[] allColors = new Color[arrayLength];
            static String[] allByteCodes = new String[arrayLength];
            static Color[] allColors2 = new Color[arrayLength2];
            static String[] allByteCodes2 = new String[arrayLength2];
            
            static int color = 0;
            static Color c2 = new Color(1,1,1);
            public static String getBinary(String filename) {
                String binary = "";
                StringBuilder sb = new StringBuilder();
                try (BufferedInputStream is = new BufferedInputStream(new FileInputStream(filename))) {
                    for (int b; (b = is.read()) != -1;) {
                        String s = "0000000" + Integer.toBinaryString(b);
                        s = s.substring(s.length() - 8); 
                        sb.append(s).append(' ');
                    }
                } catch (FileNotFoundException e) {
                    System.out.println("Error,file not found");
                    e.printstacktrace();
                } catch (IOException e) {
                    // Todo Auto-generated catch block
                    e.printstacktrace();
                }
                //System.out.println(sb);
                binary = sb.toString();
                binary = binary.replaceAll(" ","");
                return binary;
            }
            
            
            static String arrayToString(Color[] s) {
                String str = "";
                for(int i = 0; i < s.length; i++) {
                    str = str + s[i].getRGB() + "\r\n";
                }
                return str;
            }
            
            
            
            
            public static Color getPixelSingleByte(String binary) throws FileNotFoundException {
                Color c = null;
                String bytes = "";
                for(int i = 0; i < arrayLength; i++) {
                    if(allByteCodes[i].contains(binary)) {
                        c2 = allColors[i];
                    }
                }
                if(c2.getRGB() == new Color(1,1).getRGB()) {
                    System.out.println("did not reconize single bytecode for binary " + binary);
                }
                return c2;
            }
            public static Color getPixelDoubleByte(String binary) throws FileNotFoundException {
                Color c = null;
                String bytes = "";
                for(int i = 0; i < arrayLength2; i++) {
                    if(allByteCodes2[i].contains(binary)) {
                        c2 = allColors2[i];
                    }
                }
                if(c2.getRGB() == new Color(1,1).getRGB()) {
                    System.out.println("did not reconize double bytecode for binary " + binary);
                }
                return c2;
            }
            
            
            
            
        public static void compress(File input,File output) throws IOException {
            Scanner scan = new Scanner(new File("SingleByteCodec.txt"));
            for(int i = 0; scan.hasNextLine(); i++) {
                String line = scan.nextLine();
                Color tempC = new Color(Integer.parseInt(line.substring(8,11)),Integer.parseInt(line.substring(11,14)),Integer.parseInt(line.substring(14)));
                
                String tempBinary = line.substring(0,8);
                allColors[i] = tempC;
                allByteCodes[i] = tempBinary;
                //System.out.println(line);
            }
            scan.close();
            Scanner scan2 = new Scanner(new File("DoubleByteCodec.txt"));
            for(int i = 0; scan2.hasNextLine(); i++) {
                String line = scan2.nextLine();
                Color tempC = new Color(Integer.parseInt(line.substring(16,19)),Integer.parseInt(line.substring(19,22)),Integer.parseInt(line.substring(22)));
                
                String tempBinary = line.substring(0,16);
                allColors2[i] = tempC;
                allByteCodes2[i] = tempBinary;
                //System.out.println(line);
            }
            scan2.close();
            
            
            String binary = getBinary(input.getAbsolutePath());
            FileWriter logWriter = new FileWriter("log.txt");
            logWriter.write(binary);
            logWriter.close();
            int height = (binary.length() / 16) / 7000;
            int width;
            
            if(height == 0) {
                height = 1;
                width = (binary.length() / 16);
            }else {
                width = 7000;
                height++;
            }
            width++;
            String subStr = "";
            int sub1 = 0;
            int sub2 = 16;
            
            BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
            int index = 0;
            for(int y = 0; y < height; y++) {
                for(int x = 0; x < width; x++) {
                    if(index % 100 == 0) {
                     System.out.println(index + "/" + width*height);
                    }
                    try {
                        subStr = binary.substring(sub1,sub2);
                        int c = getPixelDoubleByte(subStr).getRGB();
                        //System.out.println(c);
                        image.setRGB(x,y,c);
                    }catch(Stringindexoutofboundsexception e) {
                        try {
                            subStr = binary.substring(sub1,sub2 - 8);
                            int c = getPixelSingleByte(subStr).getRGB();
                            //System.out.println(c);
                            image.setRGB(x,c);
                        }catch(Stringindexoutofboundsexception e2) {
                        int c = new Color(255,255,255).getRGB();
                        image.setRGB(x,c);
                        }
                    }
                        
                    
                        
                    
                    index = index + 1;
                    sub1 = sub1 + 16;
                    sub2 = sub2 + 16;
                    //System.out.println(subStr);
                }
            }
            ImageIO.write(image,"png",output);
            System.out.println("Done!");
        }
        
        
        
        
        }
    

解压类:

    package image_to_png;
    
    import java.awt.Color;
    import java.awt.image.BufferedImage;
    import java.io.bufferedoutputstream;
    import java.io.File;
    import java.io.FileNotFoundException;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.io.OutputStream;
    import java.util.Scanner;
    
    import javax.imageio.ImageIO;
    
    public class Uncompress {
        static int arrayLength = 256;
        static int arrayLength2 = 51344;
        static Color[] allColors = new Color[arrayLength];
        static String[] allByteCodes = new String[arrayLength];
        static Color[] allColors2 = new Color[arrayLength2];
        static String[] allByteCodes2 = new String[arrayLength2];
        
        static byte[] decodeBinary(String s) {
            
            if (s.length() % 8 != 0) throw new IllegalArgumentException(
                "Binary data length must be multiple of 8");
            byte[] data = new byte[s.length() / 8];
            for (int i = 0; i < s.length(); i++) {
                char c = s.charat(i);
                if (c == '1') {
                    data[i >> 3] |= 0x80 >> (i & 0x7);
                } else if (c != '0') {
                    throw new IllegalArgumentException("Invalid char in binary string");
                }
            }
            return data;
        }
        
        
    
        
        
        
        public static String getSingleByte(Color c) throws FileNotFoundException {
            String binary = "NOBINARY";
            int color = 0;
            for (int i = 0; i < arrayLength; i++) {
                //System.out.println(c.getRGB());
                if(allColors[i].getRGB() == c.getRGB()) {
                    binary = allByteCodes[i];
                    
                    
                }
                
            }
            
            if(binary == "NOBINARY") {
                if(c.getRGB() == -1) {
                    
                }else {
                //System.out.println("Could not find a bytecode for color " + c.getRGB());
                return "!@#NOBINARY#@!";
                }
            }
            return binary;
        }
        public static String getDoubleByte(Color c) throws FileNotFoundException {
            String binary = "NOBINARY";
            int color = 0;
            for (int i = 0; i < arrayLength2; i++) {
                //System.out.println(c.getRGB());
                if(allColors2[i].getRGB() == c.getRGB()) {
                    binary = allByteCodes2[i];
                    
                    
                }
                
            }
            
            if(binary == "NOBINARY") {
                if(c.getRGB() == -1) {
                    
                }else {
                //System.out.println("Could not find a bytecode for color " + c.getRGB());
                return "!@#NOBINARY#@!";
                }
            }
            return binary;
        }
        
        
        
        public static void uncompress(File input,16);
                allColors2[i] = tempC;
                allByteCodes2[i] = tempBinary;
                //System.out.println(line);
            }
            scan2.close();
            int index = 0;
            String binary = "";
            BufferedImage jzip = ImageIO.read(input);
            int width = jzip.getWidth();
            int height = jzip.getHeight();
            boolean allDoublebyte = false;
            
            for(int y = 0; y < height; y++) {
                for(int x = 0; x < width; x++) {
                    index = index + 1;
                    if(index % 100 == 0) {
                        System.out.println(index + "/" + width * height);
                    }
                        String tempBinary = getDoubleByte(new Color(jzip.getRGB(x,y)));
                        if(tempBinary == "!@#NOBINARY#@!") {
                            tempBinary = getSingleByte(new Color(jzip.getRGB(x,y)));
                        }
                        binary = binary + tempBinary;
                        
                    
                }
            }
            binary = binary.replaceAll("[^0-1]","");
            Scanner sc = new Scanner(new File("log.txt"));
            String oldBinary = sc.nextLine();
            FileWriter logWriter = new FileWriter("log.txt");
            
            logWriter.write("Old file binary: " + oldBinary + "\r\n" + "\r\n" + "New file binary: " + binary);
            logWriter.close();
            java.nio.file.Files.write(output.toPath(),decodeBinary(binary));
            
        }
        
        
        
        
        
    }

这里是编解码器和 .java 文件链接

https://drive.google.com/drive/folders/1OlZ7tA2VEBPcyCjt2dPTmWEemN9ENC_C

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)