Diff
checker
文本
文本
圖像
文檔
Excel
文件夾
Legal
Enterprise
桌面版
定價
登入
下載 Diffchecker 桌面版
比較文本
尋找兩個文字檔案之間的差異
工具
歷史
即時編輯器
摺疊未變更行
關閉換行
檢視
拆分
統一
比對精度
智能
單詞
字符
語法突出顯示
選擇語法
忽略
文字轉換
前往第一個差異
編輯輸入
Diffchecker Desktop
執行Diffchecker最安全的方式。取得Diffchecker桌面應用程式:您的差異永遠不會離開您的電腦!
取得桌面版
Vul4j-8_diff
建立於
3 年前
差異永不過期
清除
匯出
分享
解釋
55 刪除
行
總計
刪除
字符
總計
刪除
要繼續使用此功能,請升級到
Diff
checker
Pro
查看價格
217 行
全部複製
24 新增
行
總計
新增
字符
總計
新增
要繼續使用此功能,請升級到
Diff
checker
Pro
查看價格
199 行
全部複製
/*
/*
* Licensed to the Apache Software Foundation (ASF) under one
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
* with the License. You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing,
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* specific language governing permissions and limitations
* under the License.
* under the License.
*/
*/
package org.apache.commons.compress.archivers.zip;
package org.apache.commons.compress.archivers.zip;
import java.io.IOException;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.CoderResult;
import java.nio.charset.CoderResult;
import java.nio.charset.CodingErrorAction;
import java.nio.charset.CodingErrorAction;
/**
/**
* A ZipEncoding, which uses a java.nio {@link
* A ZipEncoding, which uses a java.nio {@link
* java.nio.charset.Charset Charset} to encode names.
* java.nio.charset.Charset Charset} to encode names.
* <p>The methods of this class are reentrant.</p>
* <p>The methods of this class are reentrant.</p>
* @Immutable
* @Immutable
*/
*/
class NioZipEncoding implements ZipEncoding, CharsetAccessor {
class NioZipEncoding implements ZipEncoding, CharsetAccessor {
private final Charset charset;
private final Charset charset;
private final boolean useReplacement;
private final boolean useReplacement;
private static final char REPLACEMENT = '?';
private static final char REPLACEMENT = '?';
private static final byte[] REPLACEMENT_BYTES = { (byte) REPLACEMENT };
private static final byte[] REPLACEMENT_BYTES = { (byte) REPLACEMENT };
private static final String REPLACEMENT_STRING = String.valueOf(REPLACEMENT);
private static final String REPLACEMENT_STRING = String.valueOf(REPLACEMENT);
private static final char[] HEX_CHARS = new char[] {
private static final char[] HEX_CHARS = new char[] {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
};
};
/**
/**
* Construct an NioZipEncoding using the given charset.
* Construct an NioZipEncoding using the given charset.
* @param charset The character set to use.
* @param charset The character set to use.
* @param useReplacement should invalid characters be replaced, or reported.
* @param useReplacement should invalid characters be replaced, or reported.
*/
*/
NioZipEncoding(final Charset charset, boolean useReplacement) {
NioZipEncoding(final Charset charset, boolean useReplacement) {
this.charset = charset;
this.charset = charset;
this.useReplacement = useReplacement;
this.useReplacement = useReplacement;
}
}
@Override
@Override
public Charset getCharset() {
public Charset getCharset() {
return charset;
return charset;
}
}
/**
/**
* @see ZipEncoding#canEncode(java.lang.String)
* @see ZipEncoding#canEncode(java.lang.String)
*/
*/
@Override
@Override
public boolean canEncode(final String name) {
public boolean canEncode(final String name) {
final CharsetEncoder enc = newEncoder();
final CharsetEncoder enc = newEncoder();
return enc.canEncode(name);
return enc.canEncode(name);
}
}
複製
已複製
複製
已複製
/**
@Override
* @see ZipEncoding#encode(java.lang.String)
public ByteBuffer encode(final String name) {
*/
final CharsetEncoder enc = newEncoder();
@Override
final CharBuffer cb = CharBuffer.wrap(name);
public ByteBuffer encode(final String name) {
CharBuffer tmp = null;
final CharsetEncoder enc = newEncoder();
ByteBuffer out = ByteBuffer.allocate(estimateInitialBufferSize(enc, cb.remaining()));
CoderResult res = null;
final CharBuffer cb = CharBuffer.wrap(name);
while (cb.remaining() > 0
|| (
res = enc.encode(cb, out, false)
).isOverflow()) {
CharBuffer tmp = null;
if (res != null &&
(res.isUnmappable() || res.isMalformed()
)) {
ByteBuffer out = ByteBuffer.allocate(estimateInitialBufferSize(enc, cb.remaining()));
int spaceForSurrogate = estimateIncrementalEncodingSize(enc, 6 * res.length());
if (spaceForSurrogate > out.remaining()) {
while (cb.remaining() > 0
) {
int charCount = 0;
final CoderResult
res = enc.encode(cb, out, false)
;
for (int i = cb.position()
; i < cb.limit(); i++) {
charCount += !enc.canEncode(cb.get(i)) ? 6 : 1;
if
(res.isUnmappable() || res.isMalformed()
) {
// write the unmappable characters in utf-16
// pseudo-URL encoding style to ByteBuffer.
int spaceForSurrogate = estimateIncrementalEncodingSize(enc, 6 * res.length());
if (spaceForSurrogate > out.remaining()) {
// if the destination buffer isn't over sized, assume that the presence of one
// unmappable character makes it likely that there will be more. Find all the
// un-encoded characters and allocate space based on those estimates.
int charCount = 0;
for (int i = cb.position()
; i < cb.limit(); i++) {
charCount += !enc.canEncode(cb.get(i)) ? 6 : 1;
}
int totalExtraSpace = estimateIncrementalEncodingSize(enc, charCount);
out = ZipEncodingHelper.growBufferBy(out, totalExtraSpace - out.remaining());
}
if (tmp == null) {
tmp = CharBuffer.allocate(6);
}
for (int i = 0; i < res.length(); ++i) {
out = encodeFully(enc, encodeSurrogate(tmp, cb.get()), out);
}
}
複製
已複製
複製
已複製
int
totalExtraSpace
= estimateIncrementalEncodingSize(enc,
charCount
);
} else if (res.isOverflow()) {
out = ZipEncodingHelper.growBufferBy(out,
totalExtraSpace - out.remaining());
int
increment
= estimateIncrementalEncodingSize(enc,
cb.remaining()
);
}
out = ZipEncodingHelper.growBufferBy(out,
increment);
if (tmp == null) {
tmp = CharBuffer.allocate(6);
}
for (int i = 0; i < res.length(); ++i) {
out = encodeFully(enc, encodeSurrogate(tmp, cb.get()), out);
}
}
複製
已複製
複製
已複製
} else if (res != null && res.isOverflow()) {
int increment = estimateIncrementalEncodingSize(enc, cb.remaining());
out = ZipEncodingHelper.growBufferBy(out, increment);
}
}
複製
已複製
複製
已複製
// tell the encoder we are done
enc.encode(cb, out, true);
// may have caused underflow, but that's been ignored traditionally
out.limit(out.position());
out.rewind();
return out;
}
}
複製
已複製
複製
已複製
enc.encode(cb, out, true);
out.limit(out.position());
out.rewind();
return out;
}
/**
/**
* @see
* @see
* ZipEncoding#decode(byte[])
* ZipEncoding#decode(byte[])
*/
*/
@Override
@Override
public String decode(final byte[] data) throws IOException {
public String decode(final byte[] data) throws IOException {
return newDecoder()
return newDecoder()
.decode(ByteBuffer.wrap(data)).toString();
.decode(ByteBuffer.wrap(data)).toString();
}
}
private static ByteBuffer encodeFully(CharsetEncoder enc, CharBuffer cb, ByteBuffer out) {
private static ByteBuffer encodeFully(CharsetEncoder enc, CharBuffer cb, ByteBuffer out) {
ByteBuffer o = out;
ByteBuffer o = out;
while (cb.hasRemaining()) {
while (cb.hasRemaining()) {
CoderResult result = enc.encode(cb, o, false);
CoderResult result = enc.encode(cb, o, false);
if (result.isOverflow()) {
if (result.isOverflow()) {
int increment = estimateIncrementalEncodingSize(enc, cb.remaining());
int increment = estimateIncrementalEncodingSize(enc, cb.remaining());
o = ZipEncodingHelper.growBufferBy(o, increment);
o = ZipEncodingHelper.growBufferBy(o, increment);
}
}
}
}
return o;
return o;
}
}
private static CharBuffer encodeSurrogate(CharBuffer cb, char c) {
private static CharBuffer encodeSurrogate(CharBuffer cb, char c) {
cb.position(0).limit(6);
cb.position(0).limit(6);
cb.put('%');
cb.put('%');
cb.put('U');
cb.put('U');
cb.put(HEX_CHARS[(c >> 12) & 0x0f]);
cb.put(HEX_CHARS[(c >> 12) & 0x0f]);
cb.put(HEX_CHARS[(c >> 8) & 0x0f]);
cb.put(HEX_CHARS[(c >> 8) & 0x0f]);
cb.put(HEX_CHARS[(c >> 4) & 0x0f]);
cb.put(HEX_CHARS[(c >> 4) & 0x0f]);
cb.put(HEX_CHARS[c & 0x0f]);
cb.put(HEX_CHARS[c & 0x0f]);
cb.flip();
cb.flip();
return cb;
return cb;
}
}
private CharsetEncoder newEncoder() {
private CharsetEncoder newEncoder() {
if (useReplacement) {
if (useReplacement) {
return charset.newEncoder()
return charset.newEncoder()
.onMalformedInput(CodingErrorAction.REPLACE)
.onMalformedInput(CodingErrorAction.REPLACE)
.onUnmappableCharacter(CodingErrorAction.REPLACE)
.onUnmappableCharacter(CodingErrorAction.REPLACE)
.replaceWith(REPLACEMENT_BYTES);
.replaceWith(REPLACEMENT_BYTES);
} else {
} else {
return charset.newEncoder()
return charset.newEncoder()
.onMalformedInput(CodingErrorAction.REPORT)
.onMalformedInput(CodingErrorAction.REPORT)
.onUnmappableCharacter(CodingErrorAction.REPORT);
.onUnmappableCharacter(CodingErrorAction.REPORT);
}
}
}
}
private CharsetDecoder newDecoder() {
private CharsetDecoder newDecoder() {
if (!useReplacement) {
if (!useReplacement) {
return this.charset.newDecoder()
return this.charset.newDecoder()
.onMalformedInput(CodingErrorAction.REPORT)
.onMalformedInput(CodingErrorAction.REPORT)
.onUnmappableCharacter(CodingErrorAction.REPORT);
.onUnmappableCharacter(CodingErrorAction.REPORT);
} else {
} else {
return charset.newDecoder()
return charset.newDecoder()
.onMalformedInput(CodingErrorAction.REPLACE)
.onMalformedInput(CodingErrorAction.REPLACE)
.onUnmappableCharacter(CodingErrorAction.REPLACE)
.onUnmappableCharacter(CodingErrorAction.REPLACE)
.replaceWith(REPLACEMENT_STRING);
.replaceWith(REPLACEMENT_STRING);
}
}
}
}
/**
/**
* Estimate the initial encoded size (in bytes) for a character buffer.
* Estimate the initial encoded size (in bytes) for a character buffer.
* <p>
* <p>
* The estimate assumes that one character consumes uses the maximum length encoding,
* The estimate assumes that one character consumes uses the maximum length encoding,
* whilst the rest use an average size encoding. This accounts for any BOM for UTF-16, at
* whilst the rest use an average size encoding. This accounts for any BOM for UTF-16, at
* the expense of a couple of extra bytes for UTF-8 encoded ASCII.
* the expense of a couple of extra bytes for UTF-8 encoded ASCII.
* </p>
* </p>
*
*
* @param enc encoder to use for estimates
* @param enc encoder to use for estimates
* @param charChount number of characters in string
* @param charChount number of characters in string
* @return estimated size in bytes.
* @return estimated size in bytes.
*/
*/
private static int estimateInitialBufferSize(CharsetEncoder enc, int charChount) {
private static int estimateInitialBufferSize(CharsetEncoder enc, int charChount) {
float first = enc.maxBytesPerChar();
float first = enc.maxBytesPerChar();
float rest = (charChount - 1) * enc.averageBytesPerChar();
float rest = (charChount - 1) * enc.averageBytesPerChar();
return (int) Math.ceil(first + rest);
return (int) Math.ceil(first + rest);
}
}
/**
/**
* Estimate the size needed for remaining characters
* Estimate the size needed for remaining characters
*
*
* @param enc encoder to use for estimates
* @param enc encoder to use for estimates
* @param charCount number of characters remaining
* @param charCount number of characters remaining
* @return estimated size in bytes.
* @return estimated size in bytes.
*/
*/
private static int estimateIncrementalEncodingSize(CharsetEncoder enc, int charCount) {
private static int estimateIncrementalEncodingSize(CharsetEncoder enc, int charCount) {
return (int) Math.ceil(charCount * enc.averageBytesPerChar());
return (int) Math.ceil(charCount * enc.averageBytesPerChar());
}
}
}
}
已保存差異
原始文本
開啟檔案
/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.commons.compress.archivers.zip; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; import java.nio.charset.CharsetEncoder; import java.nio.charset.CoderResult; import java.nio.charset.CodingErrorAction; /** * A ZipEncoding, which uses a java.nio {@link * java.nio.charset.Charset Charset} to encode names. * <p>The methods of this class are reentrant.</p> * @Immutable */ class NioZipEncoding implements ZipEncoding, CharsetAccessor { private final Charset charset; private final boolean useReplacement; private static final char REPLACEMENT = '?'; private static final byte[] REPLACEMENT_BYTES = { (byte) REPLACEMENT }; private static final String REPLACEMENT_STRING = String.valueOf(REPLACEMENT); private static final char[] HEX_CHARS = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; /** * Construct an NioZipEncoding using the given charset. * @param charset The character set to use. * @param useReplacement should invalid characters be replaced, or reported. */ NioZipEncoding(final Charset charset, boolean useReplacement) { this.charset = charset; this.useReplacement = useReplacement; } @Override public Charset getCharset() { return charset; } /** * @see ZipEncoding#canEncode(java.lang.String) */ @Override public boolean canEncode(final String name) { final CharsetEncoder enc = newEncoder(); return enc.canEncode(name); } /** * @see ZipEncoding#encode(java.lang.String) */ @Override public ByteBuffer encode(final String name) { final CharsetEncoder enc = newEncoder(); final CharBuffer cb = CharBuffer.wrap(name); CharBuffer tmp = null; ByteBuffer out = ByteBuffer.allocate(estimateInitialBufferSize(enc, cb.remaining())); while (cb.remaining() > 0) { final CoderResult res = enc.encode(cb, out, false); if (res.isUnmappable() || res.isMalformed()) { // write the unmappable characters in utf-16 // pseudo-URL encoding style to ByteBuffer. int spaceForSurrogate = estimateIncrementalEncodingSize(enc, 6 * res.length()); if (spaceForSurrogate > out.remaining()) { // if the destination buffer isn't over sized, assume that the presence of one // unmappable character makes it likely that there will be more. Find all the // un-encoded characters and allocate space based on those estimates. int charCount = 0; for (int i = cb.position() ; i < cb.limit(); i++) { charCount += !enc.canEncode(cb.get(i)) ? 6 : 1; } int totalExtraSpace = estimateIncrementalEncodingSize(enc, charCount); out = ZipEncodingHelper.growBufferBy(out, totalExtraSpace - out.remaining()); } if (tmp == null) { tmp = CharBuffer.allocate(6); } for (int i = 0; i < res.length(); ++i) { out = encodeFully(enc, encodeSurrogate(tmp, cb.get()), out); } } else if (res.isOverflow()) { int increment = estimateIncrementalEncodingSize(enc, cb.remaining()); out = ZipEncodingHelper.growBufferBy(out, increment); } } // tell the encoder we are done enc.encode(cb, out, true); // may have caused underflow, but that's been ignored traditionally out.limit(out.position()); out.rewind(); return out; } /** * @see * ZipEncoding#decode(byte[]) */ @Override public String decode(final byte[] data) throws IOException { return newDecoder() .decode(ByteBuffer.wrap(data)).toString(); } private static ByteBuffer encodeFully(CharsetEncoder enc, CharBuffer cb, ByteBuffer out) { ByteBuffer o = out; while (cb.hasRemaining()) { CoderResult result = enc.encode(cb, o, false); if (result.isOverflow()) { int increment = estimateIncrementalEncodingSize(enc, cb.remaining()); o = ZipEncodingHelper.growBufferBy(o, increment); } } return o; } private static CharBuffer encodeSurrogate(CharBuffer cb, char c) { cb.position(0).limit(6); cb.put('%'); cb.put('U'); cb.put(HEX_CHARS[(c >> 12) & 0x0f]); cb.put(HEX_CHARS[(c >> 8) & 0x0f]); cb.put(HEX_CHARS[(c >> 4) & 0x0f]); cb.put(HEX_CHARS[c & 0x0f]); cb.flip(); return cb; } private CharsetEncoder newEncoder() { if (useReplacement) { return charset.newEncoder() .onMalformedInput(CodingErrorAction.REPLACE) .onUnmappableCharacter(CodingErrorAction.REPLACE) .replaceWith(REPLACEMENT_BYTES); } else { return charset.newEncoder() .onMalformedInput(CodingErrorAction.REPORT) .onUnmappableCharacter(CodingErrorAction.REPORT); } } private CharsetDecoder newDecoder() { if (!useReplacement) { return this.charset.newDecoder() .onMalformedInput(CodingErrorAction.REPORT) .onUnmappableCharacter(CodingErrorAction.REPORT); } else { return charset.newDecoder() .onMalformedInput(CodingErrorAction.REPLACE) .onUnmappableCharacter(CodingErrorAction.REPLACE) .replaceWith(REPLACEMENT_STRING); } } /** * Estimate the initial encoded size (in bytes) for a character buffer. * <p> * The estimate assumes that one character consumes uses the maximum length encoding, * whilst the rest use an average size encoding. This accounts for any BOM for UTF-16, at * the expense of a couple of extra bytes for UTF-8 encoded ASCII. * </p> * * @param enc encoder to use for estimates * @param charChount number of characters in string * @return estimated size in bytes. */ private static int estimateInitialBufferSize(CharsetEncoder enc, int charChount) { float first = enc.maxBytesPerChar(); float rest = (charChount - 1) * enc.averageBytesPerChar(); return (int) Math.ceil(first + rest); } /** * Estimate the size needed for remaining characters * * @param enc encoder to use for estimates * @param charCount number of characters remaining * @return estimated size in bytes. */ private static int estimateIncrementalEncodingSize(CharsetEncoder enc, int charCount) { return (int) Math.ceil(charCount * enc.averageBytesPerChar()); } }
更改後文本
開啟檔案
/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.commons.compress.archivers.zip; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; import java.nio.charset.CharsetEncoder; import java.nio.charset.CoderResult; import java.nio.charset.CodingErrorAction; /** * A ZipEncoding, which uses a java.nio {@link * java.nio.charset.Charset Charset} to encode names. * <p>The methods of this class are reentrant.</p> * @Immutable */ class NioZipEncoding implements ZipEncoding, CharsetAccessor { private final Charset charset; private final boolean useReplacement; private static final char REPLACEMENT = '?'; private static final byte[] REPLACEMENT_BYTES = { (byte) REPLACEMENT }; private static final String REPLACEMENT_STRING = String.valueOf(REPLACEMENT); private static final char[] HEX_CHARS = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; /** * Construct an NioZipEncoding using the given charset. * @param charset The character set to use. * @param useReplacement should invalid characters be replaced, or reported. */ NioZipEncoding(final Charset charset, boolean useReplacement) { this.charset = charset; this.useReplacement = useReplacement; } @Override public Charset getCharset() { return charset; } /** * @see ZipEncoding#canEncode(java.lang.String) */ @Override public boolean canEncode(final String name) { final CharsetEncoder enc = newEncoder(); return enc.canEncode(name); } @Override public ByteBuffer encode(final String name) { final CharsetEncoder enc = newEncoder(); final CharBuffer cb = CharBuffer.wrap(name); CharBuffer tmp = null; ByteBuffer out = ByteBuffer.allocate(estimateInitialBufferSize(enc, cb.remaining())); CoderResult res = null; while (cb.remaining() > 0 || (res = enc.encode(cb, out, false)).isOverflow()) { if (res != null && (res.isUnmappable() || res.isMalformed())) { int spaceForSurrogate = estimateIncrementalEncodingSize(enc, 6 * res.length()); if (spaceForSurrogate > out.remaining()) { int charCount = 0; for (int i = cb.position(); i < cb.limit(); i++) { charCount += !enc.canEncode(cb.get(i)) ? 6 : 1; } int totalExtraSpace = estimateIncrementalEncodingSize(enc, charCount); out = ZipEncodingHelper.growBufferBy(out, totalExtraSpace - out.remaining()); } if (tmp == null) { tmp = CharBuffer.allocate(6); } for (int i = 0; i < res.length(); ++i) { out = encodeFully(enc, encodeSurrogate(tmp, cb.get()), out); } } else if (res != null && res.isOverflow()) { int increment = estimateIncrementalEncodingSize(enc, cb.remaining()); out = ZipEncodingHelper.growBufferBy(out, increment); } } enc.encode(cb, out, true); out.limit(out.position()); out.rewind(); return out; } /** * @see * ZipEncoding#decode(byte[]) */ @Override public String decode(final byte[] data) throws IOException { return newDecoder() .decode(ByteBuffer.wrap(data)).toString(); } private static ByteBuffer encodeFully(CharsetEncoder enc, CharBuffer cb, ByteBuffer out) { ByteBuffer o = out; while (cb.hasRemaining()) { CoderResult result = enc.encode(cb, o, false); if (result.isOverflow()) { int increment = estimateIncrementalEncodingSize(enc, cb.remaining()); o = ZipEncodingHelper.growBufferBy(o, increment); } } return o; } private static CharBuffer encodeSurrogate(CharBuffer cb, char c) { cb.position(0).limit(6); cb.put('%'); cb.put('U'); cb.put(HEX_CHARS[(c >> 12) & 0x0f]); cb.put(HEX_CHARS[(c >> 8) & 0x0f]); cb.put(HEX_CHARS[(c >> 4) & 0x0f]); cb.put(HEX_CHARS[c & 0x0f]); cb.flip(); return cb; } private CharsetEncoder newEncoder() { if (useReplacement) { return charset.newEncoder() .onMalformedInput(CodingErrorAction.REPLACE) .onUnmappableCharacter(CodingErrorAction.REPLACE) .replaceWith(REPLACEMENT_BYTES); } else { return charset.newEncoder() .onMalformedInput(CodingErrorAction.REPORT) .onUnmappableCharacter(CodingErrorAction.REPORT); } } private CharsetDecoder newDecoder() { if (!useReplacement) { return this.charset.newDecoder() .onMalformedInput(CodingErrorAction.REPORT) .onUnmappableCharacter(CodingErrorAction.REPORT); } else { return charset.newDecoder() .onMalformedInput(CodingErrorAction.REPLACE) .onUnmappableCharacter(CodingErrorAction.REPLACE) .replaceWith(REPLACEMENT_STRING); } } /** * Estimate the initial encoded size (in bytes) for a character buffer. * <p> * The estimate assumes that one character consumes uses the maximum length encoding, * whilst the rest use an average size encoding. This accounts for any BOM for UTF-16, at * the expense of a couple of extra bytes for UTF-8 encoded ASCII. * </p> * * @param enc encoder to use for estimates * @param charChount number of characters in string * @return estimated size in bytes. */ private static int estimateInitialBufferSize(CharsetEncoder enc, int charChount) { float first = enc.maxBytesPerChar(); float rest = (charChount - 1) * enc.averageBytesPerChar(); return (int) Math.ceil(first + rest); } /** * Estimate the size needed for remaining characters * * @param enc encoder to use for estimates * @param charCount number of characters remaining * @return estimated size in bytes. */ private static int estimateIncrementalEncodingSize(CharsetEncoder enc, int charCount) { return (int) Math.ceil(charCount * enc.averageBytesPerChar()); } }
尋找差異