📄 pdfreader.java
字号:
tokens.seek(tokens.getStartxref()); tokens.nextToken(); if (!tokens.getStringValue().equals("startxref")) throw new IOException("startxref not found."); tokens.nextToken(); if (tokens.getTokenType() != PRTokeniser.TK_NUMBER) throw new IOException("startxref is not followed by a number."); int startxref = tokens.intValue(); tokens.seek(startxref); int ch; do { ch = tokens.read(); } while (ch != -1 && ch != 't'); if (ch == -1) throw new IOException("Unexpected end of file."); tokens.backOnePosition(); tokens.nextValidToken(); if (!tokens.getStringValue().equals("trailer")) throw new IOException("trailer not found."); trailer = (PdfDictionary)readPRObject(); if (trailer.get(PdfName.ENCRYPT) != null) { encrypted = true; throw new IOException("Encrypted files are not supported."); } PdfNumber xrefSize = (PdfNumber)trailer.get(PdfName.SIZE); xref = new int[xrefSize.intValue()]; tokens.seek(startxref); readXrefSection(); PdfDictionary trailer2 = trailer; while (true) { PdfNumber prev = (PdfNumber)trailer2.get(PdfName.PREV); if (prev == null) break; tokens.seek(prev.intValue()); readXrefSection(); trailer2 = (PdfDictionary)readPRObject(); } } protected void readXrefSection() throws IOException { tokens.nextValidToken(); if (!tokens.getStringValue().equals("xref")) tokens.throwError("xref subsection not found"); int start = 0; int end = 0; int pos = 0; int gen = 0; while (true) { tokens.nextValidToken(); if (tokens.getStringValue().equals("trailer")) break; if (tokens.getTokenType() != PRTokeniser.TK_NUMBER) tokens.throwError("Object number of the first object in this xref subsection not found"); start = tokens.intValue(); tokens.nextValidToken(); if (tokens.getTokenType() != PRTokeniser.TK_NUMBER) tokens.throwError("Number of entries in this xref subsection not found"); end = tokens.intValue() + start; if (start == 1) { // fix incorrect start number int back = tokens.getFilePointer(); tokens.nextValidToken(); pos = tokens.intValue(); tokens.nextValidToken(); gen = tokens.intValue(); if (pos == 0 && gen == 65535) { --start; --end; } tokens.seek(back); } if (xref.length < end) { // fix incorrect size int xref2[] = new int[end]; System.arraycopy(xref, 0, xref2, 0, xref.length); xref = xref2; } for (int k = start; k < end; ++k) { tokens.nextValidToken(); pos = tokens.intValue(); tokens.nextValidToken(); gen = tokens.intValue(); tokens.nextValidToken(); if (tokens.getStringValue().equals("n")) { if (xref[k] == 0) xref[k] = pos; } else if (tokens.getStringValue().equals("f")) { if (xref[k] == 0) xref[k] = -1; } else tokens.throwError("Invalid cross-reference entry in this xref subsection"); } } } protected void rebuildXref() throws IOException { tokens.seek(0); int xr[][] = new int[1024][]; int top = 0; trailer = null; byte line[] = new byte[64]; for (;;) { int pos = tokens.getFilePointer(); if (!tokens.readLineSegment(line)) break; if (line[0] == 't') { if (!PdfEncodings.convertToString(line, null).startsWith("trailer")) continue; pos = tokens.getFilePointer(); try { PdfDictionary dic = (PdfDictionary)readPRObject(); if (dic.get(PdfName.ROOT) != null) trailer = dic; else tokens.seek(pos); } catch (Exception e) { tokens.seek(pos); } } else if (line[0] >= '0' && line[0] <= '9') { int obj[] = PRTokeniser.checkObjectStart(line); if (obj == null) continue; int num = obj[0]; int gen = obj[1]; if (num >= xr.length) { int newLength = num * 2; int xr2[][] = new int[newLength][]; System.arraycopy(xr, 0, xr2, 0, top); xr = xr2; } if (num >= top) top = num + 1; if (xr[num] == null || gen >= xr[num][1]) { obj[0] = pos; xr[num] = obj; } } } if (trailer == null) throw new IOException("trailer not found."); if (trailer.get(PdfName.ENCRYPT) != null) throw new IOException("Encrypted files are not supported."); xref = new int[top]; for (int k = 0; k < top; ++k) { int obj[] = xr[k]; if (obj != null) xref[k] = obj[0]; } } protected PdfDictionary readDictionary() throws IOException { PdfDictionary dic = new PdfDictionary(); while (true) { tokens.nextValidToken(); if (tokens.getTokenType() == PRTokeniser.TK_END_DIC) break; if (tokens.getTokenType() != PRTokeniser.TK_NAME) tokens.throwError("Dictionary key is not a name."); PdfName name = new PdfName(tokens.getStringValue()); PdfObject obj = readPRObject(); int type = obj.type(); if (-type == PRTokeniser.TK_END_DIC) tokens.throwError("Unexpected '>>'"); if (-type == PRTokeniser.TK_END_ARRAY) tokens.throwError("Unexpected ']'"); dic.put(name, obj); } return dic; } protected PdfArray readArray() throws IOException { PdfArray array = new PdfArray(); while (true) { PdfObject obj = readPRObject(); int type = obj.type(); if (-type == PRTokeniser.TK_END_ARRAY) break; if (-type == PRTokeniser.TK_END_DIC) tokens.throwError("Unexpected '>>'"); array.add(obj); } return array; } protected PdfObject readPRObject() throws IOException { tokens.nextValidToken(); int type = tokens.getTokenType(); switch (type) { case PRTokeniser.TK_START_DIC: { PdfDictionary dic = readDictionary(); int pos = tokens.getFilePointer(); // be careful in the trailer. May not be a "next" token. if (tokens.nextToken() && tokens.getStringValue().equals("stream")) { int ch = tokens.read(); if (ch == '\r') ch = tokens.read(); if (ch != '\n') tokens.backOnePosition(); PRStream stream = new PRStream(this, tokens.getFilePointer()); stream.putAll(dic); return stream; } else { tokens.seek(pos); return dic; } } case PRTokeniser.TK_START_ARRAY: return readArray(); case PRTokeniser.TK_NUMBER: return new PdfNumber(tokens.getStringValue()); case PRTokeniser.TK_STRING: return new PdfString(tokens.getStringValue(), null); case PRTokeniser.TK_NAME: return new PdfName(tokens.getStringValue()); case PRTokeniser.TK_REF: return new PRIndirectReference(this, tokens.getReference(), tokens.getGeneration()); default: return new PdfLiteral(-type, tokens.getStringValue()); } } public static byte[] FlateDecode(byte in[]) { byte b[] = FlateDecode(in, true); if (b == null) return FlateDecode(in, false); return b; } public static byte[] FlateDecode(byte in[], boolean strict) { ByteArrayInputStream stream = new ByteArrayInputStream(in); InflaterInputStream zip = new InflaterInputStream(stream); ByteArrayOutputStream out = new ByteArrayOutputStream(); byte b[] = new byte[strict ? 4092 : 1]; try { int n; while ((n = zip.read(b)) >= 0) { out.write(b, 0, n); } zip.close(); out.close(); return out.toByteArray(); } catch (Exception e) { if (strict) return null; return out.toByteArray(); } } public static byte[] ASCIIHexDecode(byte in[]) { ByteArrayOutputStream out = new ByteArrayOutputStream(); boolean first = true; int n1 = 0; for (int k = 0; k < in.length; ++k) { int ch = in[k] & 0xff; if (ch == '>') break; if (PRTokeniser.isWhitespace(ch)) continue; int n = PRTokeniser.getHex(ch); if (n == -1) throw new RuntimeException("Illegal character in ASCIIHexDecode."); if (first) n1 = n; else out.write((byte)((n1 << 4) + n)); first = !first; } if (!first) out.write((byte)(n1 << 4)); return out.toByteArray(); } public static byte[] ASCII85Decode(byte in[]) { ByteArrayOutputStream out = new ByteArrayOutputStream(); int state = 0; int chn[] = new int[5]; for (int k = 0; k < in.length; ++k) { int ch = in[k] & 0xff; if (ch == '~') break; if (PRTokeniser.isWhitespace(ch)) continue; if (ch == 'z' && state == 0) { out.write(0); out.write(0); out.write(0); out.write(0); continue; } if (ch < '!' || ch > 'u') throw new RuntimeException("Illegal character in ASCII85Decode."); chn[state] = ch - '!'; ++state; if (state == 5) { state = 0; int r = 0; for (int j = 0; j < 5; ++j) r = r * 85 + chn[j]; out.write((byte)(r >> 24)); out.write((byte)(r >> 16)); out.write((byte)(r >> 8)); out.write((byte)r); } } int r = 0; if (state == 1) throw new RuntimeException("Illegal length in ASCII85Decode."); if (state == 2) { r = chn[0] * 85 + chn[1]; out.write((byte)r); } else if (state == 3) { r = chn[0] * 85 * 85 + chn[1] * 85 + chn[2]; out.write((byte)(r >> 8)); out.write((byte)r); } else if (state == 4) { r = chn[0] * 85 * 85 * 85 + chn[1] * 85 * 85 + chn[2] * 85 + chn[3]; out.write((byte)(r >> 16)); out.write((byte)(r >> 8)); out.write((byte)r); } return out.toByteArray(); } public static byte[] LZWDecode(byte in[]) { ByteArrayOutputStream out = new ByteArrayOutputStream(); LZWDecoder lzw = new LZWDecoder(); lzw.decode(in, out); return out.toByteArray(); } /** Checks if the document had errors and was rebuilt. * @return true if rebuilt. * */ public boolean isRebuilt() { return this.rebuilt; } public PdfDictionary getPageN(int pageNum) { if (pageNum > pages.length) return null; return pages[pageNum - 1]; } public PRIndirectReference getPageOrigRef(int pageNum) { if (pageNum > pageRefs.length) return null; return pageRefs[pageNum - 1]; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -