Diff
checker
टेक्स्ट
टेक्स्ट
छवियां
दस्तावेज़
Excel
फ़ोल्डर्स
Legal
Enterprise
डेस्कटॉप
मूल्य
साइन इन करें
Diffchecker डेस्कटॉप डाउनलोड करें
टेक्स्ट की तुलना करें
दो टेक्स्ट फ़ाइलों के बीच अंतर ढूंढें
उपकरण
इतिहास
रियल-टाइम एडिटर
अपरिवर्तित संक्षिप्त करें
लाइन रैप बंद
लेआउट
विभाजित
संयुक्त
परिवर्तन हाइलाइट करें
स्मार्ट
शब्द
अक्षर
सिंटैक्स हाइलाइटिंग
सिंटैक्स चुनें
अनदेखा करें
टेक्स्ट बदलें
पहले अंतर पर जाएँ
इनपुट संपादित करें
Diffchecker Desktop
Diffchecker चलाने का सबसे सुरक्षित तरीका। Diffchecker Desktop ऐप पाएं: आपके diffs कभी आपके कंप्यूटर से बाहर नहीं जाते!
Desktop पाएं
Vul4j-8_diff
बनाया गया
3 वर्ष पहले
Diff कभी समाप्त नहीं होता
साफ़
निर्यात करें
शेयर करें
समझाएं
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());
}
}
}
}
सेव किए गए Diffs
ऑरिजनल टेक्स्ट
फ़ाइल खोलें
/* * 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()); } }
अंतर खोजें