图像读写java.lang.IllegalArgumentException

图像读写java.lang.IllegalArgumentException,java,file-io,javax.imageio,Java,File Io,Javax.imageio,我想创建一个非常简单的加密/解密项目。但首先,我想读取jpg文件并使用给定密码将其写入文件,然后再次读取该文件并检查文件中的密码和提供的密码,但我得到: Exception in thread "main" java.lang.IllegalArgumentException: im == null! at javax.imageio.ImageIO.write(Unknown Source) at javax.imageio.ImageIO.write(Unknown Sour

我想创建一个非常简单的加密/解密项目。但首先,我想读取jpg文件并使用给定密码将其写入文件,然后再次读取该文件并检查文件中的密码和提供的密码,但我得到:

Exception in thread "main" java.lang.IllegalArgumentException: im == null!
    at javax.imageio.ImageIO.write(Unknown Source)
    at javax.imageio.ImageIO.write(Unknown Source)
    at GSM.AES.deccryption(AES.java:105)
    at GSM.AES.main(AES.java:27)
我的代码:

public static void main(String args[]) 
        {
            myWrite();
            String encryptedFilePath = System.getProperty("user.dir")+ "\\"+"Encrypted"+".mmlooloo";
            String destinationFilePath = System.getProperty("user.dir") + "\\";
            try {
                myRead(encryptedFilePath,destinationFilePath,"123456");
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return;
        }
我的加密:

 public static void myWrite() {

            try {

                System.out.println("Plesase Enter Number Of Pages !!!!!");
                BufferedReader bufferRead = new BufferedReader(new InputStreamReader(System.in));
                int numberOfPage = Integer.valueOf(bufferRead.readLine().toString());

                String dirName=  System.getProperty("user.dir")+"\\";


                byte[] base64StringEnc;
                ByteArrayOutputStream baos=new ByteArrayOutputStream(1000);
                FileOutputStream  myMatLabFileEnc = null;

                String filePath = System.getProperty("user.dir")+ "\\"+"Encrypted"+".mmlooloo";
                myMatLabFileEnc = new FileOutputStream (filePath);
                String imagFileName;
                String imgPathString;
                String password = "123456";
                myMatLabFileEnc.write(password.getBytes());
                myMatLabFileEnc.write("\n".getBytes());

               for(int i = 1 ; i<=numberOfPage ;i++)
               {    

                     imagFileName = Integer.toString(i) +".jpg";         
                     BufferedImage img=ImageIO.read(new File(dirName,imagFileName));
                     ImageIO.write(img, "jpg", baos);
                     baos.flush();

                     myMatLabFileEnc.write(baos.toByteArray());
                     myMatLabFileEnc.write("\n".getBytes());

                     baos.reset();
                     imgPathString = dirName + imagFileName;
                     File  f = new File(imgPathString);
                     f.delete();

               }
                     myMatLabFileEnc.close();
                     baos.close();
                     return;

                } catch (FileNotFoundException ex) {
                    System.out.println(ex.toString());
            }catch(IOException ex){
                System.out.println(ex.toString());
            }
        }
而AES.java:105是:

ImageIO.write(imagRecover, "jpg", new File(encryptedFileDir,outputRecoverdFileName));

我检查了ImageCover是否为空,但我不知道为什么?我想你可以试一下,只需将你的图像文件命名为1.jpg、2.jpg等等……

免责声明:这不是完整的答案,但它太长,无法发表评论

这就是我所说的评论:

首先不要对图像进行解码/编码。只需复制字节

使用此代码,您将不会重新压缩JPEG,因此不会丢失质量

而不是以下代码:

imagFileName = Integer.toString(i) +".jpg";         
BufferedImage img=ImageIO.read(new File(dirName,imagFileName));
ImageIO.write(img, "jpg", baos);
baos.flush();
只需将文件中的字节复制到baos,如下所示:

imagFileName = Integer.toString(i) +".jpg";         
InputStream input = new FileInputStream(new File(dirName, imagFileName));
try {
    copy(input, baos);
}
finally {
    input.close();
}
复制方法:

public void copy(InputStream input, OutputStream output) throws IOException {
    byte[] buffer = new byte[1024];
    int len;

    while ((len = input.read(buffer, 0, buffer.length)) >= 0) {
        output.write(buffer, 0, len);
    }
}
同样,在解密部分,替换:

byte[] bytearray = encryptedImag.getBytes();
BufferedImage imagRecover=ImageIO.read(new ByteArrayInputStream(bytearray));
String outputRecoverdFileName = Integer.toString(i)+"_recoverd.jpg";
ImageIO.write(imagRecover, "jpg", new File(encryptedFileDir,outputRecoverdFileName));
与:


你在写二进制数据。你不能保证在一个图像的二进制中没有一行的结尾。可能有很多的卡尔返回和结束线内的东西。。。您希望完全复制的每个线性图像都会使imageio.read失败并返回null,正如javadoc中针对该方法所述。我建议您在写入之前对每个图像进行base64编码,并使用printwriter将thw文件视为文本文件。否则,你应该尝试像thoae这样的WAD文件,保存每个文件的位置和长度。。。你读过关于java.util.zip的文章吗???@eduyayo谢谢,它很有效,但是为什么我会失去质量呢?例如,我的原始图像是551kB,但我的恢复是181KB。我使用Baase64编码-解码方法进行写入和读取。@mmlooloo当使用ImageIO.write时。。。您正在使用压缩/质量的默认参数。如果这些与您的输入文件已有的设置不匹配,您将得到一个更小/更大的文件。@haraldK谢谢您,如果您能告诉我该怎么做,我不会失去任何品质,我将接受您的回答。非常感谢您,现在我想我可以实现任何加密算法,对吗?!!!只要在解密后可以复制相同的字节,就可以继续使用了:-很好,特别是关于不使用字节[]的字符串。Java的特殊之处在于字符串是Unicode,能够将所有脚本组合在一个文本中。因此,在给定的编码中总是会转换为二进制数据,或者默认为操作系统的。这种转换不能在纯二进制数据上无损工作。
byte[] bytearray = encryptedImag.getBytes();
BufferedImage imagRecover=ImageIO.read(new ByteArrayInputStream(bytearray));
String outputRecoverdFileName = Integer.toString(i)+"_recoverd.jpg";
ImageIO.write(imagRecover, "jpg", new File(encryptedFileDir,outputRecoverdFileName));
byte[] bytearray = encryptedImag.getBytes();
InputStream input = new ByteArrayInputStream(bytearray));
String outputRecoverdFileName = Integer.toString(i) + "_recoverd.jpg";
OutputStream output = new FileOutputStream(new File(encryptedFileDir, outputRecoverdFileName)));
try {
    copy(input, output);
}
finally {
    output.close();
}