Оба DictReader
и DictWriter
принимают произвольные аргументы, включая delimiter
, и передают их нижележащему объекту reader
или writer
в качестве документации говорит:
class
csv.DictReader
(…)Все остальные необязательные аргументы или аргументы ключевых слов передаются в базовый
blockquote>reader
экземпляр.
class
csv.DictWriter
(…)Любые другие необязательные или ключевые аргументы передаются в базовый [ 119] экземпляр.
blockquote>Изменение соответствующей строки в вашем коде выше на
r = csv.DictReader(infile, delimiter=";")
должно работать как положено.
Как прокомментировано, не ясно, что вы подразумеваете под слиянием.
Взятие доступного ввода «случайно» из любого осложняется InputStream.available
не обязательно дает вам полезный ответ и блокирует поведение потоков. Вам потребуется два потока для чтения из потоков и последующей передачи данных, скажем, через java.io.Piped (In | Out) putStream
(хотя у этих классов есть проблемы). В качестве альтернативы для некоторых типов потоков может быть возможно использовать другой интерфейс, например java.nio
неблокирующие каналы.
Если вы хотите, чтобы полное содержимое первого входного потока сопровождалось вторым : new java.io.SequenceInputStream (s1, s2)
.
java.io.SequenceInputStream
может быть тем, что вам нужно. Он принимает перечисление потоков и выводит содержимое первого потока, затем второго и т. Д., Пока все потоки не станут пустыми.
Вы можете написать собственную реализацию InputStream
, которая сделает это. Пример:
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();
}
}
Этот код не проверен, поэтому ваш пробег может отличаться.
Не то, чтобы я мог придумать. Вам, вероятно, придется прочитать содержимое двух потоков в byte [], а затем создать из него ByteArrayInputStream.
Вот Реализация MVar, специфичная для байтовых массивов (обязательно добавьте собственное определение пакета). Отсюда легко записать входной поток в объединенные потоки. Я могу опубликовать это тоже, если потребуется.
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();
}
}
}
}