Читать/записать в файл устройства с тайм -аутомJAVA

Программисты JAVA общаются здесь
Anonymous
Читать/записать в файл устройства с тайм -аутом

Сообщение Anonymous »

Я в настоящее время пишу драйвер принтера в Java 1.6. Мне нужно иметь возможность читать/записать в файл устройства (/dev/usb/lp0) с тайм -аутом . Я использую обертку вокруг randomaccessfile, а затем использую канал через RAF, когда хочу читать/написать. Канал позволяет мне определить тайм -аут, когда я пишу. Но текущая проблема, с которой у меня есть, заключается в том, что в случае тайм -аута канал становится поврежденным, и я получаю закрытое канал, в следующий раз, когда я пытаюсь читать или написать. Я пробовал разные вещи, в том числе не использовать канал (который не допускает тайм -аута) и воссоздание Arandomaccessfile каждый раз, когда я читаю и пишу, но до сих пор я не мог заставить его работать. < /P>
public class ThreadSafeRafChannel extends ThreadSafeRaf {
final ExecutorService executor = Executors.newSingleThreadExecutor();
private Exception currentException = null;

public ThreadSafeRafChannel(final String port) throws FileNotFoundException {
super(port);
}

/**
* Écrit un tableau de bytes sur le fichier associé au RandomAccessFile.
* @param b le tableau de bytes à écrire
* @throws InterruptedException, ExecutionException, TimeoutException
* @throws IOException
*/
public synchronized void write(final byte[] b, final long timeout) throws InterruptedException, ExecutionException, TimeoutException {

final Future future = executor.submit(new Callable() {
public Void call() throws Exception {
final ByteBuffer buf = ByteBuffer.wrap(b);
while (buf.hasRemaining()) {
raf.getChannel().write(buf);
}
addToBuffer(Direction.WRITE, b);
return null;
}
});

try {
if (future != null) {
logWrite(b);
future.get(timeout, TimeUnit.MILLISECONDS);
currentException = null;
}
else {
logger.warn("write(): impossible de créer un future pour écriture.");
}
}
catch (final InterruptedException e) {
cancel(future);
throw e;
}
catch (final ExecutionException e) {
cancel(future);
throw e;
}
catch (final TimeoutException e) {
cancel(future);
throw e;
}
}

/**
* Effectue une lecture sur le fichier associé au RandomAccessFile.
* S'arrête dès une fin de fichier.
* @return le tableau de bytes lu
* @throws IOException
*/
public synchronized byte[] read() throws InterruptedException, ExecutionException, TimeoutException {
final Future future = executor.submit(new Callable() {
public byte[] call() throws Exception {
final List byteList = new ArrayList();
final ByteBuffer buffer = ByteBuffer.allocate(1);

while (true) {
buffer.clear();
int bytesRead = raf.getChannel().read(buffer);
if (bytesRead == -1) {
break;
}

buffer.flip();
while (buffer.hasRemaining()) {
byteList.add(buffer.get());
}
}

final byte[] result = UTIL_ESCPOS.toByteArray(byteList);
if (result.length > 0) {
addToBuffer(Direction.READ, result);
}
currentException = null;
return result;
}
});

try {
if (future != null) {
final byte[] result = future.get(PrinterConfig.TO_READ, TimeUnit.MILLISECONDS);
if (result != null && result.length > 0) {
logRead(result);
}
return result;
}
else {
logger.warn("read(): impossible de créer un future pour écriture.");
}
return null;
}
catch (InterruptedException e) {
handleReadException(e, future);
throw e;
}
catch (ExecutionException e) {
handleReadException(e, future);
throw e;
}
catch (TimeoutException e) {
handleReadException(e, future);
throw e;
}
}

private void cancel(final Future future) {
if (future != null) {
future.cancel(true);
}
}

private void handleReadException(final Exception e, final Future future) {
cancel(future);
if (currentException == null) {
UTIL_LOG_PRINTER.logException(this, "read", e);
logger.debug(formatDeviceFileInfos());
logger.debug(formatPrinterIoSnapshot());
currentException = e;
}
}

public synchronized void shutdown() {
executor.shutdownNow();
}
}

public abstract class ThreadSafeRaf implements DeviceFileAccessor {
/** Nombre d'opération à garder en mémoire. */
protected final static int BUFFER_LIST_SIZE = 20;

/**
* Mode d'écriture sur le RandomAccessFile.
*
  • *
  • rws = sync data + metadata (plus lent)
    *
  • rwd = sync data only (plus rapide et toujours safe)
    *
*/
protected final static String FILE_MODE = "rwd";

protected final Log logger = Log.getInstance();
protected final String port;
protected RandomAccessFile raf;
protected final LinkedBlockingDeque buffer = new LinkedBlockingDeque(BUFFER_LIST_SIZE);

public ThreadSafeRaf(final String port) throws FileNotFoundException {
this.port = port;
this.raf = new RandomAccessFile(port, FILE_MODE);
logger.info("ThreadSafeRaf::construct(): RAF #" + System.identityHashCode(this) + " created for " + port + " inode=" + iNode());
}

/**
* Logue une lecture.
* @param b les bytes à loguer
*/
protected void logRead(final byte[] b) {
logIo("READ ", b);
}

/**
* Logue une écriture.
* @param b les bytes à loguer
*/
protected void logWrite(final byte[] b) {
logIo("WRITE", b);
}

/**
* Logue une lecture ou une écriture.
* @param rw la direction
* @param b les bytes
*/
protected void logIo(final String rw, final byte[] b) {
int loggedLength;
try {
loggedLength = PrinterConfig.LOGGED_BYTES_MAX_LENGTH;
}
catch (final Exception e) {
loggedLength = 16;
}
logger.debug(rw + " : " + UtilEscPos.UTIL_ESCPOS.getReadable(b, loggedLength, false) + " (" + b.length + "bytes)");
logger.debug(" " + UtilEscPos.UTIL_ESCPOS.getReadable(b, loggedLength, true ) + " (" + b.length + "bytes)");
}

/**
* Ajoute une entrée au buffer, retire la plus ancienne si nécessaire.
* @param direction direction de l'opération
* @param bytes contenu de l'opération
*/
protected void addToBuffer(final Direction direction, final byte[] bytes) {
if (buffer.remainingCapacity() == 0) {
buffer.removeFirst();
}
buffer.addLast(new PrinterInputOutput(direction, bytes));
}

/**
* Ferme le RandomAccessFile.
* @throws IOException
*/
public synchronized void close() throws IOException {
if (raf != null) {
raf.close();
} else {
logger.warn("close(): skipping raf.close() because raf is already null.");
}
}

/**
* Retourne l'existence du fichier associé au RandomAccessFile.
* @return true si le fichier existe
*/
public boolean exists() {
return new File(this.port).exists();
}

/**
* Retourne l'iNode fichier associé au RandomAccessFile.
* @return l'iNode ou "ERROR"
*/
protected String iNode() {
String iNode = "";
try {
iNode = UTIL_FILE.getFileInode(port);
}
catch (final Exception e) {
UTIL_LOG_PRINTER.logException(this, "iNode", e);
iNode = "ERROR";
}

return iNode;
}

/**
* Affiche les informations sur le fichier associé au RandomAccessFile.
* @return l'existence et l'iNode du fichier
*/
public String formatDeviceFileInfos() {
return UTIL_OBJECT.new DisplayedObject(this)
.withMember("port", port)
.withMember("exists()", exists())
.withMember("iNode()", iNode())
.toString();
}

/**
* Affiche les dernières opérations de lcture et d'écriture.
* @return les opérations contenues dans le buffer
*/
protected String formatPrinterIoSnapshot() {
final StringBuffer sb = new StringBuffer("Snapshot I/O printer:\n");
for (final PrinterInputOutput io: buffer) {
sb.append(" " + io.toString() + "\n");
}
return sb.toString();
}

@Override
public String toString() {
return this.getClass().getSimpleName() + "@" + System.identityHashCode(this) + "(port: " + this.port + ", exists: " + exists() + ", iNode: " + iNode() + ")";
}
}


Подробнее здесь: https://stackoverflow.com/questions/796 ... th-timeout

Вернуться в «JAVA»