Có hai InputStream trong Java, có cách nào hợp nhất chúng để bạn kết thúc bằng một InputStream cung cấp cho bạn đầu ra của cả hai luồng không? Làm sao?Làm cách nào để hợp nhất hai luồng đầu vào trong Java?
Trả lời
Như đã nhận xét, không rõ ý bạn là gì khi hợp nhất.
Sử dụng đầu vào có sẵn "ngẫu nhiên" hoặc là phức tạp bởi InputStream.available
không nhất thiết phải cung cấp cho bạn một câu trả lời hữu ích và hoạt động chặn luồng. Bạn sẽ cần hai luồng để đọc từ các luồng và sau đó truyền lại dữ liệu qua, ví dụ: java.io.Piped(In|Out)putStream
(mặc dù các lớp đó có vấn đề). Ngoài ra đối với một số loại luồng, có thể sử dụng một giao diện khác, ví dụ: java.nio
các kênh không chặn.
Nếu bạn muốn toàn bộ nội dung của luồng đầu vào đầu tiên theo sau là dòng thứ hai: new java.io.SequenceInputStream(s1, s2)
.
Ồ, rất hay, tôi mới học được điều gì đó mới mẻ. SequenceInputStream về cơ bản giống với CatInputStream của tôi, nhưng sử dụng các Liệt kê kế thừa thay vì, nói, một LinkedList. :-) –
Khi hack phần đầu của câu trả lời, thật khó để giải quyết trong trường hợp chung nhưng đối với các trường hợp cụ thể của FileInputStream (và cũng có thể là ổ cắm?), Bạn có thể instanceof/cast và tạo ra một kênh. (Các luồng khác có thể sử dụng Channels.newChannel để tạo giao diện nhất quán, nhưng sẽ không có chất lượng không chặn.) –
Bộ sưu tập.bộ đếm là bạn của bạn. Tôi quên một phần của phần đầu tiên của tôi - sẽ chỉnh sửa. –
Không phải là tôi có thể nghĩ đến. Bạn có lẽ sẽ phải đọc nội dung của hai dòng vào một byte [] và sau đó tạo ra một ByteArrayInputStream từ đó.
Upvote cho một giải pháp đơn giản, dễ hiểu, khả thi. Có thể không có hành vi bắt buộc nếu chặn là quan trọng (hoặc chúng rất lớn). –
Bạn có thể viết triển khai InputStream
tùy chỉnh thực hiện việc này. Ví dụ:
import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;
import java.util.Deque;
import java.util.LinkedList;
public class CatInputStream extends InputStream {
private final Deque<InputStream> streams;
public CatInputStream(InputStream... streams) {
this.streams = new LinkedList<InputStream>();
Collections.addAll(this.streams, streams);
}
private void nextStream() throws IOException {
streams.removeFirst().close();
}
@Override
public int read() throws IOException {
int result = -1;
while (!streams.isEmpty()
&& (result = streams.getFirst().read()) == -1) {
nextStream();
}
return result;
}
@Override
public int read(byte b[], int off, int len) throws IOException {
int result = -1;
while (!streams.isEmpty()
&& (result = streams.getFirst().read(b, off, len)) == -1) {
nextStream();
}
return result;
}
@Override
public long skip(long n) throws IOException {
long skipped = 0L;
while (skipped < n && !streams.isEmpty()) {
int thisSkip = streams.getFirst().skip(n - skipped);
if (thisSkip > 0)
skipped += thisSkip;
else
nextStream();
}
return skipped;
}
@Override
public int available() throws IOException {
return streams.isEmpty() ? 0 : streams.getFirst().available();
}
@Override
public void close() throws IOException {
while (!streams.isEmpty())
nextStream();
}
}
Mã này không được kiểm tra, vì vậy số dặm của bạn có thể thay đổi.
Điều này không giống với SequenceInputStream, theo gợi ý của Merzbow? –
Xin lỗi, nhưng tackline đề xuất SequenceInputStream đầu tiên (và tôi đã +1 anh ấy cho điều đó). Trong SO, câu trả lời tốt nhất sớm nhất sẽ thắng; bạn không bao giờ biết nếu câu trả lời sau đó là đạo văn. Ngoài ra, đọc nhận xét của tôi về câu trả lời của tackline cho một so sánh giữa SequenceInputStream và CatInputStream (Tôi có quan điểm của mình về việc sử dụng Collections.enumeration). –
Nếu người downvoted câu trả lời của tôi đã làm như vậy vì nhận xét cuối cùng của tôi, tôi xin lỗi; Tôi nên giải thích tốt hơn: nếu tôi viết một câu trả lời hóa ra là một bản sao (hoặc tập hợp con) của một câu trả lời được đăng trước đó, tôi thường xóa nó, biết rằng tôi sẽ không bao giờ nhận được bất kỳ điểm nào cho nó. Trên SO, nó thực sự là "Súng nhanh nhất ở phương Tây" (tìm kiếm tiêu đề câu hỏi đó). –
java.io.SequenceInputStream
có thể là những gì bạn cần. Nó chấp nhận việc đếm các luồng và sẽ xuất nội dung của luồng đầu tiên, sau đó là luồng thứ hai, v.v. cho đến khi tất cả các luồng đều trống.
Dưới đây là triển khai MVar dành riêng cho mảng byte (đảm bảo thêm định nghĩa gói của riêng bạn). Từ đây, nó là tầm thường để viết một luồng đầu vào trên các dòng đã hợp nhất. Tôi cũng có thể đăng bài đó nếu được yêu cầu.
import java.nio.ByteBuffer;
public final class MVar {
private static enum State {
EMPTY, ONE, MANY
}
private final Object lock;
private State state;
private byte b;
private ByteBuffer bytes;
private int length;
public MVar() {
lock = new Object();
state = State.EMPTY;
}
public final void put(byte b) {
synchronized (lock) {
while (state != State.EMPTY) {
try {
lock.wait();
} catch (InterruptedException e) {}
}
this.b = b;
state = State.ONE;
lock.notifyAll();
}
}
public final void put(byte[] bytes, int offset, int length) {
if (length == 0) {
return;
}
synchronized (lock) {
while (state != State.EMPTY) {
try {
lock.wait();
} catch (InterruptedException e) {}
}
this.bytes = ByteBuffer.allocateDirect(length);
this.bytes.put(bytes, offset, length);
this.bytes.position(0);
this.length = length;
state = State.MANY;
lock.notifyAll();
}
}
public final byte take() {
synchronized (lock) {
while (state == State.EMPTY) {
try {
lock.wait();
} catch (InterruptedException e) {}
}
switch (state) {
case ONE: {
state = State.EMPTY;
byte b = this.b;
lock.notifyAll();
return b;
}
case MANY: {
byte b = bytes.get();
state = --length <= 0 ? State.EMPTY : State.MANY;
lock.notifyAll();
return b;
}
default:
throw new AssertionError();
}
}
}
public final int take(byte[] bytes, int offset, int length) {
if (length == 0) {
return 0;
}
synchronized (lock) {
while (state == State.EMPTY) {
try {
lock.wait();
} catch (InterruptedException e) {}
}
switch (state) {
case ONE:
bytes[offset] = b;
state = State.EMPTY;
lock.notifyAll();
return 1;
case MANY:
if (this.length > length) {
this.bytes.get(bytes, offset, length);
this.length = this.length - length;
synchronized (lock) {
lock.notifyAll();
}
return length;
}
this.bytes.get(bytes, offset, this.length);
this.bytes = null;
state = State.EMPTY;
length = this.length;
lock.notifyAll();
return length;
default:
throw new AssertionError();
}
}
}
}
- 1. Cách hợp nhất hai hoặc nhiều luồng
- 2. Làm thế nào để "hợp nhất" hai URI trong Java?
- 3. Hợp nhất hai byte trong java/android
- 4. Làm cách nào để đệm luồng đầu vào/đầu ra/tệp Java của tôi đúng cách?
- 5. Làm cách nào để hợp nhất hai ngày trong JavaScript?
- 6. Làm cách nào để hợp nhất hai lớp trong PHP?
- 7. Làm cách nào để kết hợp hai ResultSets trong Java?
- 8. Hợp nhất hai đối tượng trong Java
- 9. Hợp nhất hai tệp XML trong Java
- 10. Làm cách nào để hợp nhất hai tài liệu pdf vào một báo cáo trong JasperReport?
- 11. Làm cách nào để hợp nhất hai BST hiệu quả?
- 12. Làm cách nào để hợp nhất các cột từ hai bảng thành một đầu ra?
- 13. Làm cách nào để hợp nhất hai danh sách IQueryable
- 14. Làm cách nào để hợp nhất hai đối tượng?
- 15. Làm cách nào để hợp nhất hai bảng MySQL?
- 16. Làm cách nào để kết hợp nhiều luồng âm thanh vào một luồng được ghi bằng Java?
- 17. làm thế nào để hợp nhất hai bảng trong postgresql
- 18. Làm cách nào để hợp nhất hai danh sách vào một danh sách?
- 19. Quy trình Java với luồng đầu vào/đầu ra
- 20. Làm cách nào để hợp nhất và duy trì thứ tự hàng của một đầu vào?
- 21. Cách đọc luồng đầu vào http
- 22. Làm cách nào để hợp nhất hai mảng bằng cách tiếp nhận các giá trị duy nhất từ mảng thứ hai có cùng khóa với mảng đầu tiên?
- 23. Làm thế nào để kiểm tra hợp nhất mà không thực sự hợp nhất đầu tiên
- 24. Có cách nào để hợp nhất hai tệp gcov vào một
- 25. Làm cách nào để hợp nhất hai mảng để tạo một mảng trong JavaScript?
- 26. Cách kết hợp hai hoặc nhiều tệp gzip/luồng
- 27. Giải mã luồng đầu vào
- 28. C++ kết nối luồng đầu ra với luồng đầu vào
- 29. Làm cách nào để hợp nhất các bảng trong R?
- 30. Làm cách nào để thêm nhãn vào một trong hai đầu của điều khiển ExtJS Slider?
Hợp nhất theo cách nào? Liền mạch tiếp tục đọc từ luồng thứ hai sau khi đọc lần đầu tiên? Tôi không quen thuộc với Java, nhưng trong C# bạn có thể làm điều này một cách dễ dàng đủ bằng cách thực hiện một lớp kế thừa từ Stream chứa tham chiếu tới cả hai luồng cơ sở và sau đó ghi đè phương thức Read. – Noldorin