Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

使用 ByteArrayOutputBuffer 替代 ByteArrayOutputStream #2873

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,11 @@
import org.jackhuang.hmcl.util.i18n.I18n;
import org.jackhuang.hmcl.util.io.CompressingUtils;
import org.jackhuang.hmcl.util.io.FileUtils;
import org.jackhuang.hmcl.util.io.IOUtils;
import org.jackhuang.hmcl.util.io.NetworkUtils;
import org.jetbrains.annotations.NotNull;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.nio.file.FileSystem;
import java.nio.file.Files;
import java.nio.file.Path;
Expand Down Expand Up @@ -294,9 +294,9 @@ class ModInfoDialog extends JFXDialogLayout {
try (FileSystem fs = CompressingUtils.createReadOnlyZipFileSystem(modInfo.getModInfo().getFile())) {
Path iconPath = fs.getPath(modInfo.getModInfo().getLogoPath());
if (Files.exists(iconPath)) {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
Files.copy(iconPath, stream);
return new ByteArrayInputStream(stream.toByteArray());
try (InputStream in = Files.newInputStream(iconPath)) {
return IOUtils.readFully(in).toInputStream();
}
}
}
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ public static AuthlibInjectorServer locateServer(String url) throws IOException

try {
AuthlibInjectorServer server = new AuthlibInjectorServer(url);
server.refreshMetadata(IOUtils.readFullyAsStringWithClosing(conn.getInputStream()));
server.refreshMetadata(IOUtils.readFullyAsStringWithoutClosing(conn.getInputStream()));
return server;
} finally {
conn.disconnect();
Expand Down
15 changes: 6 additions & 9 deletions HMCLCore/src/main/java/org/jackhuang/hmcl/auth/offline/Skin.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,10 @@
import org.jackhuang.hmcl.task.Task;
import org.jackhuang.hmcl.util.StringUtils;
import org.jackhuang.hmcl.util.gson.JsonUtils;
import org.jackhuang.hmcl.util.io.ByteArrayBuilder;
import org.jackhuang.hmcl.util.io.FileUtils;
import org.jetbrains.annotations.Nullable;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
Expand Down Expand Up @@ -245,22 +244,20 @@ protected EnumCheckETag shouldCheckETag() {

@Override
protected Context getContext(URLConnection conn, boolean checkETag) throws IOException {
ByteArrayBuilder output = ByteArrayBuilder.createFor(conn);
return new Context() {
final ByteArrayOutputStream baos = new ByteArrayOutputStream();

@Override
public void write(byte[] buffer, int offset, int len) {
baos.write(buffer, offset, len);
public int read(InputStream inputStream) throws IOException {
return output.read(inputStream);
}

@Override
public void close() throws IOException {
if (!isSuccess()) return;

setResult(new ByteArrayInputStream(baos.toByteArray()));

setResult(output.toInputStream());
if (checkETag) {
repository.cacheBytes(baos.toByteArray(), conn);
repository.cacheBytes(output.getArray(), output.size(), conn);
}
}
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@
import org.jackhuang.hmcl.task.Task;
import org.jackhuang.hmcl.util.gson.JsonUtils;
import org.jackhuang.hmcl.util.io.FileUtils;
import org.jackhuang.hmcl.util.io.IOUtils;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
Expand Down Expand Up @@ -77,8 +77,8 @@ public void execute() throws Exception {
throw new IOException("Cannot make directory " + forgeFile.getParent());

ZipEntry forgeEntry = zipFile.getEntry(installProfile.getInstall().getFilePath());
try (InputStream is = zipFile.getInputStream(forgeEntry); OutputStream os = new FileOutputStream(forgeFile)) {
IOUtils.copyTo(is, os);
try (InputStream is = zipFile.getInputStream(forgeEntry)) {
Files.copy(is, forgeFile.toPath());
}

setResult(installProfile.getVersionInfo()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,14 @@
import org.jackhuang.hmcl.task.FileDownloadTask.IntegrityCheck;
import org.jackhuang.hmcl.task.Task;
import org.jackhuang.hmcl.util.DigestUtils;
import org.jackhuang.hmcl.util.io.ByteArrayBuilder;
import org.jackhuang.hmcl.util.io.FileUtils;
import org.jackhuang.hmcl.util.io.IOUtils;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
Expand Down Expand Up @@ -164,12 +164,12 @@ private static boolean validateJar(byte[] data, List<String> checksums) throws I
JarInputStream jar = new JarInputStream(new ByteArrayInputStream(data));
JarEntry entry = jar.getNextJarEntry();
while (entry != null) {
byte[] eData = IOUtils.readFullyWithoutClosing(jar);
ByteArrayBuilder eData = IOUtils.readFullyWithoutClosing(jar);
if (entry.getName().equals("checksums.sha1")) {
hashes = new String(eData, StandardCharsets.UTF_8).split("\n");
hashes = eData.toString().split("\n");
}
if (!entry.isDirectory()) {
files.put(entry.getName(), DigestUtils.digestToString("SHA-1", eData));
files.put(entry.getName(), DigestUtils.digestToString("SHA-1", eData.getArray(), eData.size()));
}
entry = jar.getNextJarEntry();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@
import org.jackhuang.hmcl.util.MurmurHash2;
import org.jackhuang.hmcl.util.Pair;
import org.jackhuang.hmcl.util.StringUtils;
import org.jackhuang.hmcl.util.io.ByteArrayBuilder;
import org.jackhuang.hmcl.util.io.HttpRequest;
import org.jackhuang.hmcl.util.io.JarUtils;
import org.jetbrains.annotations.Nullable;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
Expand Down Expand Up @@ -140,21 +140,22 @@ public SearchResult search(String gameVersion, @Nullable RemoteModRepository.Cat

@Override
public Optional<RemoteMod.Version> getRemoteVersionByLocalFile(LocalModFile localModFile, Path file) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ByteArrayBuilder builder;
try (InputStream stream = Files.newInputStream(file)) {
builder = ByteArrayBuilder.createFor(stream);
byte[] buf = new byte[1024];
int len;
while ((len = stream.read(buf, 0, buf.length)) != -1) {
for (int i = 0; i < len; i++) {
byte b = buf[i];
if (b != 0x9 && b != 0xa && b != 0xd && b != 0x20) {
baos.write(b);
builder.write(b);
}
}
}
}

long hash = Integer.toUnsignedLong(MurmurHash2.hash32(baos.toByteArray(), baos.size(), 1));
long hash = Integer.toUnsignedLong(MurmurHash2.hash32(builder.getArray(), builder.size(), 1));

Response<FingerprintMatchesResult> response = HttpRequest.POST(PREFIX + "/v1/fingerprints")
.json(mapOf(pair("fingerprints", Collections.singletonList(hash))))
Expand Down
8 changes: 2 additions & 6 deletions HMCLCore/src/main/java/org/jackhuang/hmcl/task/FetchTask.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
import org.jackhuang.hmcl.event.EventBus;
import org.jackhuang.hmcl.util.CacheRepository;
import org.jackhuang.hmcl.util.ToStringBuilder;
import org.jackhuang.hmcl.util.io.IOUtils;
import org.jackhuang.hmcl.util.io.NetworkUtils;
import org.jackhuang.hmcl.util.io.ResponseCodeException;

Expand Down Expand Up @@ -132,15 +131,12 @@ public void execute() throws Exception {
long contentLength = conn.getContentLength();
try (Context context = getContext(conn, checkETag); InputStream stream = conn.getInputStream()) {
int lastDownloaded = 0, downloaded = 0;
byte[] buffer = new byte[IOUtils.DEFAULT_BUFFER_SIZE];
while (true) {
if (isCancelled()) break;

int len = stream.read(buffer);
int len = context.read(stream);
if (len == -1) break;

context.write(buffer, 0, len);

downloaded += len;

if (contentLength >= 0) {
Expand Down Expand Up @@ -224,7 +220,7 @@ public String toString() {
protected static abstract class Context implements Closeable {
private boolean success;

public abstract void write(byte[] buffer, int offset, int len) throws IOException;
public abstract int read(InputStream inputStream) throws IOException;

public final void withResult(boolean success) {
this.success = success;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,12 @@
import org.jackhuang.hmcl.util.io.ChecksumMismatchException;
import org.jackhuang.hmcl.util.io.CompressingUtils;
import org.jackhuang.hmcl.util.io.FileUtils;
import org.jackhuang.hmcl.util.io.IOUtils;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;
import java.nio.file.FileSystem;
Expand Down Expand Up @@ -189,49 +191,54 @@ protected void useCachedResult(Path cache) throws IOException {

@Override
protected Context getContext(URLConnection conn, boolean checkETag) throws IOException {
Path temp = Files.createTempFile(null, null);
RandomAccessFile rFile = new RandomAccessFile(temp.toFile(), "rw");
MessageDigest digest = integrityCheck == null ? null : integrityCheck.createDigest();

return new Context() {
private final MessageDigest digest = integrityCheck == null ? null : integrityCheck.createDigest();
private final byte[] buffer = new byte[IOUtils.DEFAULT_BUFFER_SIZE];
private final Path tempFile = Files.createTempFile(null, null);
private final OutputStream outputStream = Files.newOutputStream(tempFile);

@Override
public void write(byte[] buffer, int offset, int len) throws IOException {
if (digest != null) {
digest.update(buffer, offset, len);
}
public int read(InputStream inputStream) throws IOException {
int read = inputStream.read(buffer);
if (read > 0) {
if (digest != null) {
digest.update(buffer, 0, read);
}

rFile.write(buffer, offset, len);
outputStream.write(buffer, 0, read);
}
return read;
}

@Override
public void close() throws IOException {
try {
rFile.close();
outputStream.close();
} catch (IOException e) {
LOG.warning("Failed to close file: " + rFile, e);
LOG.warning("Failed to close file: " + tempFile, e);
}

if (!isSuccess()) {
try {
Files.delete(temp);
Files.delete(tempFile);
} catch (IOException e) {
LOG.warning("Failed to delete file: " + rFile, e);
LOG.warning("Failed to delete file: " + tempFile, e);
}
return;
}

for (IntegrityCheckHandler handler : integrityCheckHandlers) {
handler.checkIntegrity(temp, file.toPath());
handler.checkIntegrity(tempFile, file.toPath());
}

Files.deleteIfExists(file.toPath());
if (!FileUtils.makeDirectory(file.getAbsoluteFile().getParentFile()))
throw new IOException("Unable to make parent directory " + file);

try {
FileUtils.moveFile(temp.toFile(), file);
FileUtils.moveFile(tempFile.toFile(), file);
} catch (Exception e) {
throw new IOException("Unable to move temp file from " + temp + " to " + file, e);
throw new IOException("Unable to move temp file from " + tempFile + " to " + file, e);
}

// Integrity check
Expand Down
18 changes: 11 additions & 7 deletions HMCLCore/src/main/java/org/jackhuang/hmcl/task/GetTask.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,11 @@
*/
package org.jackhuang.hmcl.task;

import org.jackhuang.hmcl.util.io.ByteArrayBuilder;
import org.jackhuang.hmcl.util.io.FileUtils;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.Charset;
Expand Down Expand Up @@ -72,23 +73,26 @@ protected void useCachedResult(Path cachedFile) throws IOException {

@Override
protected Context getContext(URLConnection conn, boolean checkETag) {
ByteArrayBuilder output = ByteArrayBuilder.createFor(conn);
return new Context() {
final ByteArrayOutputStream baos = new ByteArrayOutputStream();

@Override
public void write(byte[] buffer, int offset, int len) {
baos.write(buffer, offset, len);
public int read(InputStream inputStream) throws IOException {
return output.read(inputStream);
}

@Override
public void close() throws IOException {
if (!isSuccess()) return;

String result = baos.toString(charset.name());
String result = output.toString(charset);
setResult(result);

if (checkETag) {
repository.cacheText(result, conn);
if (charset == UTF_8) {
repository.cacheBytes(output.getArray(), output.size(), conn);
} else {
repository.cacheBytes(result.getBytes(UTF_8), conn);
}
}
}
};
Expand Down