2014-04-22 3 views
0

У меня возникла проблема с чтением с DataOutputStream с Scanner. Следующий код выходит из строя с исключением несоответствия входа.Совместимость сканера с OutputStreams

DataOutputStream o = new DataOutputStream(new FileOutputStream("temp")); 
    o.writeByte(1); 
    o.flush(); o.close(); 

    Scanner i = new Scanner(new FileInputStream("temp")); 
    System.out.println(i.nextByte()); 
    i.close(); 

И какие выходные потоки совместимы со сканером? Есть ли пара выходных/входных потоков, которые созданы для чтения и записи всех примитивных типов и строковых строк? Мне действительно нужен не устаревший метод readLine(), и все входные потоки, которые я видел, которые имеют этот метод, устарели.

EDIT: Входные и выходные потоки будут через сокеты для приложения Client/Server. Вот весь соответствующий код для каждой стороны:

SERVER

package server; 

import java.io.DataOutputStream; 
import java.io.IOException; 
import java.net.ServerSocket; 
import java.net.Socket; 
import java.util.HashMap; 
import java.util.Scanner; 

/** 
* Server class handles all clients that wish to read a file stored on this 
* server's 
* database. Also connects to other servers to share some information. 
* 
* @author Josh Wilkins 
*/ 
public class Server{ 

//Server message type constants 
private static final byte REPLY = 0; 
private static final byte YES = 1; 
private static final byte NO = 2; 
private static final byte UPDATE = 3; 

private final int id; 
private final ServerSocket fileServer;  //connection point for clients 
private HashMap<String, FileObject> files; //list of files in database, hashed by file name 

/** 
* Creates a new file server with given id on the specified port. 
* <p> 
* @param id 
* @param port 
* <p> 
* @throws IOException 
*/ 
public Server(int id, int port) throws IOException{ 
    this.id = id; 
    fileServer = new ServerSocket(port); 
    files = new HashMap<>(); 
} 

/** 
* Loops forever, accepting new clients and creating threads to handle 
* them. 
* <p> 
* @throws IOException 
*/ 
public void acceptClients() throws IOException{ 
    while(true){ 
     Socket client = fileServer.accept(); 
     (new ClientHandler(client)).run(); 
    } 
} 

/** 
* Sends most updated version of specified file to specified server. Will 
* only send update if the server should host the file. UNIMPLEMENTED. 
* <p> 
* @throws UnsupportedOperationException 
*/ 
private void sendUpdate(int server, FileObject file){ 
    //TODO 
    throw new UnsupportedOperationException("Not supported yet."); 
} 

/** 
* Creates a new file in the database with the file name contained in the 
* string file. 
* <p> 
* @param file the file name of the new file object 
*/ 
private synchronized void createFileObject(String file){ 
    //TODO: Reject files not hashed to this server 
    try{ 
     files.put(file, new FileObject(file)); 
    } catch(IOException ex){ 
     System.err.println("Failed to create file: " + file); 
     ex.printStackTrace(System.err); 
    } 
} 

/** 
* Determines if this server is allowed to initiate a write request for a 
* file by giving the client the most current version number. 
* <p> 
* @param file the file name of the file in question 
* <p> 
* @return true if allowed to initiate, false otherwise 
*/ 
private boolean canInitiate(String file){ 
    int hash0 = file.hashCode() % 7; 
    int hash1 = (file.hashCode() + 1) % 7; 
    return id == hash0 || id == hash1; 
} 

/** 
* Threaded class to handle all requests from a single client connection. 
*/ 
class ClientHandler extends Thread{ 
    //Client message type constants 
    private static final byte READ = 0; 
    private static final byte WRITE = 1; 
    private static final byte COMMIT = 2; 
    private static final byte ABORT = 3; 

    private Socket client; 
    private DataOutputStream out; 
    private Scanner in; 
    private HashMap<String, Integer> pendingUpdates; 

    /** 
    * Sets up data input and output streams from given client socket. 
    * <p> 
    * @param client the socket that this client is connected to 
    */ 
    public ClientHandler(Socket client) throws IOException{ 
     this.client = client; 
     out = new DataOutputStream(client.getOutputStream()); 
     in = new Scanner(client.getInputStream()); 
     pendingUpdates = new HashMap<>(); 
    } 

    /** 
    * Listens for messages coming from client until the connection is 
    * closed on the client side. 
    */ 
    @Override 
    public void run(){ 
     //Loops until the client closes the connection, then hasNext returns false 
     while(in.hasNext()){ 
      //wait for the next message type to be written to the stream 
      byte msgType = in.nextByte(); 
      switch(msgType){ 
       case READ: 
        parseRead(); 
        break; 
       case WRITE: 
        parseWrite(); 
        break; 
       case COMMIT: 
        parseCommit(); 
        break; 
       case ABORT: 
        parseAbort(); 
        break; 
       default: 
      } 
     } 

     //connection is no longer needed, try to clean everything up 
     try{ 
      in.close(); 
      out.close(); 
      client.close(); 
     } catch(IOException ex){ 
      System.err.println("Failed to close client at " + client.getInetAddress()); 
      ex.printStackTrace(System.err); 
     } 
    } 

    /** 
    * Parses read message from client by collecting data from the input 
    * stream and processing it. Assumes the message type byte has already 
    * been read. If the file exists in the database, its contents are 
    * written to the client, otherwise a null string is written. 
    */ 
    private void parseRead(){ 
     //TODO: Reject files not hashed to this server 
     String file = in.nextLine().trim(); //get requested file name (should end with \n) 
     String contents = ""; 
     if(files.containsKey(file)){ 
      try{ 
       contents = files.get(file).getContents(); 
      } catch(IOException ex){ 
       System.err.println("Error reading from file: " + file); 
       ex.printStackTrace(System.err); 
      } 
     } else { 
      //TODO: Need to decide how to handle no such file 
      //   - create file and return empty 
      //   - just return empty, but don't create 
      //   - return some error indicator (change file to "-1" or "File Not Found") 
      contents = ""; 
     } 
     //send REPLY message to client 
     sendReply(file, contents); 
    } 

    /** 
    * Parses write message from client by collecting data form the input 
    * stream and processing it. Assumes the message type byte has already 
    * been read. If the file does not exist, one is created immediately 
    * regardless of further success. If the version number is viable, or 
    * if this server can initiate a write for the given file, the update is 
    * queued with the respective FileObject. The client is sent a YES or 
    * NO answer depending on success of queueing the update. 
    */ 
    private void parseWrite(){ 
     //TODO: Reject files not hashed to this server 
     int version = in.nextInt();       //get version first 
     String file = in.nextLine().trim();     //get file name 
     String contents = in.useDelimiter("\\Z").next(); //read entire remaining stream for contents 
     boolean queued = false; 

     //Create file if it does not exist yet. 
     if(!files.containsKey(file)){ 
      createFileObject(file); 
     } 

     //queue update to file object 
     try{ 
      //only queue if version is given or if this server can initiate 
      if(version > 0){ 
       queued = files.get(file).queueUpdate(contents, version); 
      } else if(version < 0 && canInitiate(file)){ 
       queued = files.get(file).queueUpdate(contents); 
       version = files.get(file).getVersion() + 1; 
      } 
     } catch(IOException ex){ 
      System.err.println("Failed to queue update to: " + file); 
      ex.printStackTrace(System.err); 
     } 

     //send response to client (positive if queued, negative if not) 
     if(queued){ 
      //TODO: What happens if an update is already queued? 
      pendingUpdates.put(file, version); 
      sendYes(version, file); 
     } else { 
      sendNo(file); 
     } 
    } 

    /** 
    * Parses commit message from client by collecting data form the input 
    * stream and processing it. Assumes the message type byte has already 
    * been read. If valid server id is read from the stream, an update 
    * message is sent to that server for the file. No response is sent to 
    * client. 
    */ 
    private void parseCommit(){ 
     //TODO: Reject files not hashed to this server 
     int failed = in.nextInt(); 
     String file = in.nextLine().trim(); 
     //TODO: Handle improper commit (no pending update) 
     int version = pendingUpdates.remove(file); 
     try{ 
      files.get(file).commitUpdate(version); 
     } catch(IOException ex){ 
      System.err.println("Failed to commit: " + file + " v. " + version); 
      ex.printStackTrace(System.err); 
     } 
     if(failed >= 0){ 
      sendUpdate(failed, files.get(file)); 
     } 
    } 

    /** 
    * Parses abort message from client by collecting data form the input 
    * stream and processing it. Assumes the message type byte has already 
    * been read. Simply removes the pending update from the queues. No 
    * response is sent to the client. 
    */ 
    private void parseAbort(){ 
     //TODO: Reject files not hashed to this server 
     String file = in.nextLine().trim(); 
     int version = pendingUpdates.remove(file); //if no update is queued this simply returns null 
     //what happens if: 
     // Integer xObj = null; 
     // int x = xObj; 
     // print(x); 
     try{ 
      files.get(file).abortUpdate(version); 
     } catch(IOException ex){ 
      System.err.println("Failed to abort: " + file + " v. " + version); 
      ex.printStackTrace(System.err); 
     } 
    } 

    /** 
    * Sends reply message to client. Assumes partial failure is impossible. 
    * <p> 
    * @param file  name of file 
    * @param contents data contained in file 
    */ 
    public void sendReply(String file, String contents){ 
     try{ 
      out.writeByte(REPLY); 
      out.writeChars(file + "\n"); //end file name with CR for easy reading 
      out.writeChars(contents); 
     } catch(IOException ex){ 
      System.err.println("Error sending REPLY(" + file + ", <" + contents.length() + ">)"); 
      ex.printStackTrace(System.err); 
     } 
    } 

    /** 
    * Sends yes message to client. Assumes partial failure is impossible. 
    * <p> 
    * @param version this updates version number 
    * @param file name of file 
    */ 
    public void sendYes(int version, String file){ 
     try{ 
      out.writeByte(YES); 
      out.writeInt(version); 
      out.writeChars(file + "\n"); 
     } catch(IOException ex){ 
      System.err.println("Error sending YES(" + version + ", " + file + ")"); 
      ex.printStackTrace(System.err); 
     } 
    } 

    /** 
    * Sends reply message to client. Assumes partial failure is impossible. 
    * <p> 
    * @param file name of file 
    */ 
    public void sendNo(String file){ 
     try{ 
      out.writeByte(NO); 
      out.writeChars(file + "\n"); 
     } catch(IOException ex){ 
      System.err.println("Error sending NO(" + file + ")"); 
      ex.printStackTrace(System.err); 
     } 
    } 
} 
} 

КЛИЕНТ

import java.io.*; 
import java.net.Socket; 
import java.util.Random; 
import java.util.Scanner; 
/** 
* Client will take as input the operations (WRITE or READ), the file it wishes to use, 
* and the servers in the network. The client will attempted to connect to three servers 
* when a WRITE is chosen and a random server for READ. The servers ranges for READ and WRITE 
* are based on a hashed value of the file name + the next in the line. 
* example: Sever 1 , Server 2 and Server 3; 
* 
* @author kattex 
*/ 
public class Client { 
private Socket socket = null; 
private Scanner inputStream = null; 
private DataOutputStream outputStream = null; 
private boolean isConnected = false; 
private int sequenceNumber = -1; 
private int response = 0; 
private byte READ = 0; 
private byte WRITE = 1; 
private byte COMMIT = 2; 
private byte ABORT = 3; 
private byte YES = 1; 
private byte NO = 2; 
private byte REPLY = 0; 

/** 
* Connect with server code running in local host or in any other host 
*/ 
private void connect(String address, int port) { 
     try { 
      // socket = new Socket("localHost", 4445); 
      System.out.println(address + "  " + port); 
      socket = new Socket(address, port); 
      //outputStream = new ObjectOutputStream(socket.getOutputStream()); 
      outputStream = new DataOutputStream(socket.getOutputStream()); 
      inputStream = new Scanner(socket.getInputStream()); 
      isConnected = true; 
     } catch (IOException e) { 
      System.out.println("Unable to connect to server " + address); 
     } 
} 

/* 
* Create a random integer within a min and max range 
*/ 
public static int randInt(int min, int max, int count) { 
    Random rand = new Random(); 
    System.out.println("randInt: " + min + "," + max + "," + count); 
    int randomNum = rand.nextInt((max - min) + 1) + min; 
    if (randomNum > count){ 
     randomNum = randomNum % count; 
     if (randomNum < 0){ 
      randomNum += count; 
     } 
    } 
    System.out.println("Random value: " + randomNum); 
    return randomNum; 
} 
/* 
* Generate hash value for server numbers 
*/ 
public static int hashFileName(String fileName, int serverCount){ 
    int number = fileName.hashCode() % serverCount; 
    if (number < 0){ 
     number += serverCount; 
    } 
    System.out.println("Hash Number: " + number); 
    return number; 
} 
/* 
* Write out the contents to a file, if the file does not exist create it 
*/ 
public static void CreateFile(String filename, String content){ 
    try { 
    File file = new File(filename); 
    // if file doesnt exists, then create it 
    if (!file.exists()) { 
     file.createNewFile(); 
    } 
    FileWriter fw = new FileWriter(file.getAbsoluteFile()); 
    BufferedWriter bw = new BufferedWriter(fw); 
    bw.write(content); 
    bw.close(); 
    System.out.println("Done"); 
} catch (IOException e) { 
      System.out.println("Erro creating file"); 
    e.printStackTrace(); 
} 
} 
/* 
* Find the next server in the list 
*/ 
public static int nextServer(int number, int count){ 
    int nextInt; 
    number++; 
    nextInt = number % count; 
    if (number < 0){ 
     number += count; 
    } 
    return nextInt; 
} 
/* 
* Send the WRITE messaget to server 
*/ 
private void sendWrite(String obj){ 
    try { 
     System.out.print("Pause..."); 
     (new Scanner(System.in)).nextLine(); 
     outputStream.writeByte(WRITE); 
     System.out.print("Pause..."); 
     (new Scanner(System.in)).nextLine(); 
     outputStream.writeInt(sequenceNumber); 
     System.out.print("Pause..."); 
     (new Scanner(System.in)).nextLine(); 
     outputStream.writeChars(obj); 
     outputStream.writeChar('\n'); 
     System.out.print("Pause..."); 
     (new Scanner(System.in)).nextLine(); 
     String contents = readFile(obj); 
     System.out.println("Contents of file " + obj); 

     outputStream.writeChars(contents); 
     System.out.print("Pause..."); 
     (new Scanner(System.in)).nextLine(); 

     System.out.println("sending message to server"); 
     int msgType = inputStream.nextByte(); 
     if (msgType == YES){    
      sequenceNumber = inputStream.nextInt(); 
      String tempFileName = inputStream.nextLine().trim(); 
      response = 1; 
      System.out.println("Receved YES for file " + tempFileName); 
     } 
     if (msgType == NO){ 
      String tempFileName = inputStream.nextLine(); 
      System.out.println("Receved NO for file " + tempFileName); 
     } 
    } catch (IOException e) { 
     System.out.println("Error writing WRITE message to server"); 
     e.printStackTrace(System.err); 
    } 
} 
/* 
    * Read the file into a string that can be sent throught a TCP socket 
    */ 
public String readFile(String fileName) throws FileNotFoundException{ 
    String output = new Scanner(new File(fileName)).useDelimiter("\\Z").next(); 
    System.out.println("File output in READFile" + output); 
    return output; 
} 
/* 
* Send Abort message to the server 
*/ 
public void sendAbort(String obj){ 
    try { 
     outputStream.writeByte(ABORT); 
     outputStream.writeChars(obj); 
     outputStream.writeChar('\n');   

     System.out.println("sending abort message to server"); 
    } catch (IOException e) { 
     e.printStackTrace(); 
     System.out.println("Error sending ABORT message to server"); 
    }  
} 
/* 
* Send commit to Server 
*/ 
public void sendCommit(int Fsvr, String obj){ 
    try { 
     outputStream.writeByte(COMMIT); 
     outputStream.writeInt(Fsvr); 
     outputStream.writeBytes(obj); 
     System.out.println("sending Commit message to server"); 
    } catch (IOException e) { 
     e.printStackTrace(); 
     System.out.println("Error sending COMMIT message to server"); 
    }  
} 
/* 
* Send READ request 
*/ 
public void sendREAD(String obj){ 

    String u; 
    try { 
     outputStream.writeByte(READ); 
     outputStream.writeChars(obj); 
     outputStream.writeChar('n'); 
     System.out.println("sending READ Request message to server"); 
     byte type = inputStream.nextByte(); 
     //File fl = new File(obj); 
     if (type == REPLY){ 
      String file = inputStream.nextLine().trim(); 
      String contents = inputStream.useDelimiter("\\z").next(); 
      CreateFile(file, contents); 
     }   
    } catch (IOException e) { 
     e.printStackTrace(); 
     System.out.println("Erorro sedning READ Request message to server"); 
    }  
} 
/** 
* @param args the command line arguments 
*/ 
public static void main(String[] args) { 
    Client client = new Client(); 

    int serverCount = 0; 
    int FSvr = -1; 

    int length = args.length; 
    String Object = "j.txt"; 
    String type = "write"; 

    int hashValue = hashFileName(Object, 7);  
    if (type.equals("write")){ 

     Client client2 = new Client(); 
     Client client3 = new Client(); 
     client.connect("localhost", 4445); 

     if (client.isConnected){ 
      client.sendWrite(Object); 
      if (client.response == 1){ 
       client2.sequenceNumber = client.sequenceNumber; 
      } 
     } 

     int nextValue = nextServer(hashValue,7); 

     //need to add commit message 
     int thirdValue = 3; 
     System.out.println("Server Numbers " + hashValue + " " + nextValue + " " + thirdValue); 
     serverCount = client.response + client2.response + client3.response; 
     System.out.println("Servercount " + serverCount); 

     if (serverCount >= 2){ 
      if(client.response != 1){FSvr = hashValue; } 
      if(client2.response != 1){FSvr = nextValue; } 
      if(client3.response != 1){FSvr = thridValue;} 

      if(client.response == 1){client.sendCommit(FSvr,Object);} 
      if(client2.response == 1){client2.sendCommit(FSvr,Object);} 
      if(client3.response == 1){client3.sendCommit(FSvr,Object);}    

     }else{ 
      if(client.response == 1){client.sendAbort(Object); } 
      if(client2.response == 1){client2.sendAbort(Object);} 
      if(client3.response == 1){client3.sendAbort(Object);} 
     }  
    } else { 
     if (type.equals("read")){ 
      int RValue = randInt(hashValue, hashValue + 2, 7); 
      System.out.println("HashVlue: " + hashValue + " RValue: " + RValue); 
      client.sendREAD(Object); 
     } 
    }   
} 
} 

Большая часть обработки сообщений на стороне сервера находится в ClientHandler. Я менее знаком с клиентской стороной, поскольку я ее не писал. Очевидно, что с этой реализацией есть InputMismatchException при чтении байта msgType со стороны сервера. Я также понял при поиске решения, что по крайней мере я должен добавить пробел между всеми полями для Scanner, чтобы разобрать их отдельно, но у меня все еще есть проблемы.

+0

Просто подтвердите, в каком потоке (текст/бинарный) вы хотите читать и писать? – Braj

+0

двоичный, хотя я буду писать много персонажей. – Jaws212

+0

оба находятся в двоичном потоке. Правильно? – Braj

ответ

1

Использование DataOutputStream и DataInputStream. Вместо строк используйте writeUTF() и readUTF(). Для эффективности поставьте буферизованные потоки внизу и очистите выходной файл перед чтением.

+0

Ничего себе, я не могу поверить, что пропустил readUTF/writeUTF. Это на самом деле гораздо больше того, что мне нужно, чем того, что я просил. В любом случае, я просто использовал аналогичную функциональность. Спасибо. – Jaws212

1

Сканер принимает Input Streams, такой как System.in, вам лучше использовать BufferedReader здесь. Например,

BufferedReader reader = new BufferReader(new FileReader("temp")); 

System.out.println(reader.readLine()); 

reader.close(); 
Смежные вопросы