题 PDF到字节数组,反之亦然


我需要将pdf转换为字节数组,反之亦然。

谁能帮我?

这就是我转换为字节数组的方式

public static byte[] convertDocToByteArray(String sourcePath) {

    byte[] byteArray=null;
    try {
        InputStream inputStream = new FileInputStream(sourcePath);


        String inputStreamToString = inputStream.toString();
        byteArray = inputStreamToString.getBytes();

        inputStream.close();
    } catch (FileNotFoundException e) {
        System.out.println("File Not found"+e);
    } catch (IOException e) {
                System.out.println("IO Ex"+e);
    }
    return byteArray;
}

如果我使用以下代码将其转换回文档,则会创建pdf。但是它说 'Bad Format. Not a pdf'

public static void convertByteArrayToDoc(byte[] b) {          

    OutputStream out;
    try {       
        out = new FileOutputStream("D:/ABC_XYZ/1.pdf");
        out.close();
        System.out.println("write success");
    }catch (Exception e) {
        System.out.println(e);
    }

24
2017-07-15 12:31


起源




答案:


您基本上需要一个帮助方法来将流读入内存。这非常有效:

public static byte[] readFully(InputStream stream) throws IOException
{
    byte[] buffer = new byte[8192];
    ByteArrayOutputStream baos = new ByteArrayOutputStream();

    int bytesRead;
    while ((bytesRead = stream.read(buffer)) != -1)
    {
        baos.write(buffer, 0, bytesRead);
    }
    return baos.toByteArray();
}

然后你打电话给:

public static byte[] loadFile(String sourcePath) throws IOException
{
    InputStream inputStream = null;
    try 
    {
        inputStream = new FileInputStream(sourcePath);
        return readFully(inputStream);
    } 
    finally
    {
        if (inputStream != null)
        {
            inputStream.close();
        }
    }
}

 混合文本和二进制数据 - 它只会导致眼泪。


29
2017-07-15 12:42



我想在readFully中需要一个额外的括号while while ...就像while((bytesRead = stream.read(buffer))!= -1) - Skeptor
@Skeptor:完成,谢谢。 - Jon Skeet
@JonSkeet - 你初始化的大小是8192 - 这个PDF文件有多大?我知道这就像问 “一段绳子有多长”,但如果你知道,也许是通用指南?我的PDF文件最多可长达20页。 - achAmháin
@notyou:这只是一个不是很大的缓冲区大小,但足够大以避免“每个字节的系统调用”。基本上,这是一个合理的默认值。 - Jon Skeet


Java 7介绍 Files.readAllBytes(),可以将PDF读入 byte[] 像这样:

import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.Files;

Path pdfPath = Paths.get("/path/to/file.pdf");
byte[] pdf = Files.readAllBytes(pdfPath);

编辑:

感谢Farooque指出:这将适用于阅读任何类型的文件,而不仅仅是PDF。所有文件最终只是一堆字节,因此可以读入一个 byte[]


21
2017-10-29 15:21



感谢导入编辑@Farooque!你是什​​么意思“通常它可以将任何给定的文件读入一个字节[]”? - Chris Clark
我测试了完美的pdf,jpg,gif,png,txt文件。由于它支持所有类型的文件,如果有人需要所有类型,那么“通常它可以将任何给定的文件读入字节[]”信息将有所帮助 - Farooque


问题是你在打电话 toString() 在...上 InputStream 对象本身。这将返回一个 String 代表 InputStream 对象不是实际的PDF文档。

您只想将PDF作为字节读取,因为PDF是二进制格式。然后你就可以写出相同的内容了 byte 数组,它将是一个有效的PDF,因为它尚未被修改。

例如以字节形式读取文件

File file = new File(sourcePath);
InputStream inputStream = new FileInputStream(file); 
byte[] bytes = new byte[file.length()];
inputStream.read(bytes);

10
2017-07-15 12:36



甚至这会将InputStream对象而不是PDF转换为Byte数组 - nisha


你可以用它来做 Apache Commons IO 不用担心内部细节。

使用 org.apache.commons.io.FileUtils.readFileToByteArray(File file) 返回类型的数据 byte[]

点击这里查看Javadoc


5
2018-02-10 19:01





你不是在创建pdf文件但实际上没有写回字节数组吗?因此您无法打开PDF。

out = new FileOutputStream("D:/ABC_XYZ/1.pdf");
out.Write(b, 0, b.Length);
out.Position = 0;
out.Close();

这是正确读取PDF到字节数组的补充。


1
2017-07-15 12:45



out.position = 0 ??我得到它
这可能没有用,因为你将它保存到文件但我遇到的问题是我将字节数组放入MemoryStream对象并将其下载到客户端。我必须将位置设置为0才能使其正常工作。 - David


调用 toString() 在...上 InputStream 不会做你认为它做的事情。即使它确实如此,PDF也包含二进制数据,因此您不希望首先将其转换为字符串。

您需要做的是从流中读取,将结果写入a ByteArrayOutputStream,然后转换 ByteArrayOutputStream 变成一个实际的 byte 通过调用数组 toByteArray()

InputStream inputStream = new FileInputStream(sourcePath);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

int data;
while( (data = inputStream.read()) >= 0 ) {
    outputStream.write(data);
}

inputStream.close();
return outputStream.toByteArray();

1
2017-07-15 12:40



一次读取一个字节并不是非常有效。最好一次复制一个块。 - Jon Skeet
@Jon - 是的,但我试图保持简单。另外,FileInputStream内部是否会进行内部缓冲以减轻这种影响? - Eric Petroelje


public static void main(String[] args) throws FileNotFoundException, IOException {
        File file = new File("java.pdf");

        FileInputStream fis = new FileInputStream(file);
        //System.out.println(file.exists() + "!!");
        //InputStream in = resource.openStream();
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        byte[] buf = new byte[1024];
        try {
            for (int readNum; (readNum = fis.read(buf)) != -1;) {
                bos.write(buf, 0, readNum); //no doubt here is 0
                //Writes len bytes from the specified byte array starting at offset off to this byte array output stream.
                System.out.println("read " + readNum + " bytes,");
            }
        } catch (IOException ex) {
            Logger.getLogger(genJpeg.class.getName()).log(Level.SEVERE, null, ex);
        }
        byte[] bytes = bos.toByteArray();

        //below is the different part
        File someFile = new File("java2.pdf");
        FileOutputStream fos = new FileOutputStream(someFile);
        fos.write(bytes);
        fos.flush();
        fos.close();
    }

1
2017-08-16 18:30





这对我有用:

try(InputStream pdfin = new FileInputStream("input.pdf");OutputStream pdfout = new FileOutputStream("output.pdf")){
    byte[] buffer = new byte[1024];
    int bytesRead;
    while((bytesRead = pdfin.read(buffer))!=-1){
        pdfout.write(buffer,0,bytesRead);
    }
}

但如果以下列方式使用,Jon的回答对我不起作用:

try(InputStream pdfin = new FileInputStream("input.pdf");OutputStream pdfout = new FileOutputStream("output.pdf")){

    int k = readFully(pdfin).length;
    System.out.println(k);
}

输出为零长度。这是为什么 ?


0
2018-04-29 17:53





这些都不适合我们,可能是因为我们的 inputstream 是 byte来自休息呼叫,而不是来自本地托管的pdf文件。有用的是什么 RestAssured 将PDF作为输入流阅读,然后使用Tika pdf阅读器解析它,然后调用 toString() 方法。

import com.jayway.restassured.RestAssured;
import com.jayway.restassured.response.Response;
import com.jayway.restassured.response.ResponseBody;

import org.apache.tika.exception.TikaException;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.parser.AutoDetectParser;
import org.apache.tika.parser.ParseContext;
import org.apache.tika.sax.BodyContentHandler;
import org.apache.tika.parser.Parser;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;

            InputStream stream = response.asInputStream();
            Parser parser = new AutoDetectParser(); // Should auto-detect!
            ContentHandler handler = new BodyContentHandler();
            Metadata metadata = new Metadata();
            ParseContext context = new ParseContext();

            try {
                parser.parse(stream, handler, metadata, context);
            } finally {
                stream.close();
            }
            for (int i = 0; i < metadata.names().length; i++) {
                String item = metadata.names()[i];
                System.out.println(item + " -- " + metadata.get(item));
            }

            System.out.println("!!Printing pdf content: \n" +handler.toString());
            System.out.println("content type: " + metadata.get(Metadata.CONTENT_TYPE));

0
2018-03-07 19:48