Java - 使用套接字通过不同的方法读取和写入文件

时间:2015-05-30 18:10:16

标签: java sockets

我基本上有一个应用程序可以让客户预订电影院的电影。它还具有管理员,可以控制用户数据库和管理电影和视图数据库的内容管理员。

此时,我们不需要使用实际的数据库,而是要读取和写入文件。我们必须通过套接字来做到这一点。这些文件位于服务器上,客户端通过套接字之间的连接获取或发送数据。

管理员,内容管理员和用户都有不同的java文件,每个文件都包含每个用户类使用的方法。所有这些java文件都在客户端。

我有以下问题。

  1. 程序的所有“逻辑”(包含方法的.java文件)是否在客户端?是否正确?

  2. 我是否必须在服务器端使用一个套接字,在客户端使用一个套接字?在这种情况下,来自不同java文件的所有方法都通过一个客户端套接字进行通信并传递数据。

  3. 不同的方法读取和写入不同的文件。如何将从客户端传递到套接字的数据告知服务器需要将其写入特定文件? (从适当的文件中读取相同)

  4. 两个更具体的例子。

    a)有一种方法可以让管理员将用户添加到Users.txt文件中。管理员通过main方法将userId(用于区分管理员,内容管理员和用户),名称,用户名和密码作为addUser()方法的参数。如何通过套接字发送数据并将其写入正确的文件?服务器端是否有一个对应的方法,它有一个将数据写入文件的编写器?此外,我是将数据作为一行还是作为不同的部分发送?

    public void createUser(int userId, String name, String username, String password){
    
        try{
    
            PrintWriter Writer = new PrintWriter(new BufferedWriter(new FileWriter("Users.txt", true)));
    
            boolean appendToFile = true;
    
            if (appendToFile) {
                Writer.println(userId + " " + name + " " + username + " " + password);
            }
    
            System.out.println("The user "+getUsername()+" was created!");
            Writer.close();
    
            }
    
            catch (IOException e) {
    
            }
    
    }
    
    b)另一种方法使客户能够根据关键词搜索电影。我们需要搜索Films.txt文件的每一行(它具有结构filmId(int); filmCategory(enum); filmTitle(string); filmDesription;)。 searchViewings()方法通过套接字发送用户提供的关键字,并且在服务器端,它需要在文件的每一行中搜索电影标题中的关键字。同样,是否有一个对应的方法,其中包含搜索文件每一行的逻辑?另外,只有关键字可用的服务器端如何知道如何使用它?

    public void searchViewings(String keyword){
    
        File inputFile = new File("Provoles.txt");
    
        String currentLine = null;
    
        boolean flag = false;
    
        try{
    
            BufferedReader Reader = new BufferedReader(new FileReader(inputFile));
    
            System.out.println("The movies that contain the keyword '"+keyword+"' have the following available viewings:");
    
            while ((currentLine = Reader.readLine()) != null) {
    
                String s = currentLine;
                String delims = ";";
                String[] tokens = s.split(delims);
    
                if (tokens[1].indexOf(keyword) != -1){
    
                    flag = true;
    
                    System.out.println("The movie with Film ID '"+tokens[0]+"' and Film Title '"+tokens[1]+"' has an available viewing at the cinema with ID '"+tokens[2]+"'.");
    
                }
    
            }   
    
            if (flag == false){
    
                System.out.println("There is no movie containing the current keyword.");
    
            }
    
            Reader.close();
    
        }
    
        catch (IOException e) {
    
        }
    }
    

    在实现任何套接字之前,上面的代码都是这样的。

    1. 最后,是否有一个使用我可以阅读或运行的多个文件的示例?

3 个答案:

答案 0 :(得分:0)

  

程序的所有“逻辑”(包含方法的.java文件)是否在客户端?是否正确?

不,不是真的必须在服务器端有一些逻辑,用Java或其他语言编写。否则,服务器无法读取文件并执行逻辑或将文件发送到客户端。

  

我是否必须在服务器端使用一个套接字,在客户端使用一个套接字?在这种情况下,来自不同java文件的所有方法都通过一个客户端套接字进行通信并传递数据。

你没必要,为此你需要至少一个插座,但你也可以使用多个插座。例如,管理员使用的套接字和客户端使用的套接字。

  

不同的方法读取和写入不同的文件。如何将从客户端传递到套接字的数据告知服务器需要将其写入特定文件? (从适当的文件中读取相同)

您可以通过套接字发送标题,例如:read / file1或write / file4。或类似的东西,重点是发送一些数据告诉服务器该做什么。

  

最后,是否有一个使用我可以阅读或运行的多个文件的示例?

到目前为止我还没有,但如果我找到一个,我会稍后进行稍后更新。

我希望这会有所帮助:)

答案 1 :(得分:0)

要回答您的第一个问题,您可以将应用程序逻辑存储在客户端(也称为胖/胖客户端)或服务器(瘦客户端)上。据我所知,没有一个确切的答案是“更好”。这真的取决于你的应用程序。如果您希望服务器完成大部分处理,则使用瘦客户端(存储在服务器上的逻辑)(对于处理能力有限的设备,如智能手机,这是理想的选择)。如果您希望在客户端上执行更多处理,或者访问服务器的带宽有限,请使用胖客户端。有很多关于胖瘦客户端的文章。您可能会发现one有用。

我在套接字上有点生疏,所以你可能想接受另一个答案的建议,但从我记得的每个客户端将有1+套接字,服务器也将有1+(取决于如何你选择实现你的连接)套接字。客户端和服务器都将使用相同的端口号。有关一些简单示例,请参阅this文章。当我尝试使用它们时,我使用ServerSocket作为服务器,使用Socket作为客户端。查看上述链接中的不同示例以获取相关信息。如果您还有其他问题,请告诉我,我会尽力详细说明。

答案 2 :(得分:0)

这是一个简单的项目,使用套接字和文件来读取和写入我之前做过的。希望查看此代码将澄清您使用自己的代码所带来的问题。由于时间限制,我没有将其转换为包含您提供的代码片段,但是如果您在看了我的代码片段之后仍然坚持使用自己的代码,我会看到我能做些什么。

如果您运行此代码,请注意以下几点:

  • 这个项目使用的服务器和客户端GUI有点混乱(我不擅长设计GUI),但功能应该仍然有用。
  • 您需要为服务器和客户端提供与命令行参数相同的端口号。您可以通过“运行”按钮下拉列表在Eclipse中执行此操作 - >运行配置... - >参数选项卡 - >键入端口号(我使用12345) - >点击运行)。为服务器和客户端执行此操作。
  • 确保在运行客户端之前运行服务器
  • 此示例仅从文件中读取。没有写作功能。
  • 客户端成功启动后,键入要读取的文件的名称(即:readfile1.txt),包括文件扩展名。
  • 这使用从根项目目录开始的相对路径名,因此如果您的Users.txt文件位于src文件夹中,则键入“src / Users.txt”。
  • 在客户端GUI顶部的客户端输入字段中键入文件名,以便在下面打印该文件的全部内容。您可以一次输入任意数量的文件名。

服务器代码

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.EOFException;
import java.io.File;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;


public class FileServer extends JFrame {
//main function
public static void main(String[] args) {
    int port = Integer.parseInt(args[0]);
    //String file = args[1];
    FileServer server = new FileServer(port);
    server.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    server.runServer();
}

//FileServer class declarations
private File file; //for this example, the file is stored in the root project directory and includes the file extension (ie: .txt, etc)
private ServerSocket ss;
private Socket connection;
private JTextField field;
private JTextArea displayArea;
private int portNum;
private ObjectOutputStream oos;
private ObjectInputStream ois;

public FileServer(int port) {
    super("Server");
    //file = new File(f); //sent from client or done here?
    portNum = port;
    field = new JTextField();
    field.setEditable(false);
    field.addActionListener(
            new ActionListener() {
                public void actionPerformed(ActionEvent event) {
                    sendData(event.getActionCommand());
                    field.setText("");
                }
            }); //ends addActionListener
    add(field, BorderLayout.NORTH);

    displayArea = new JTextArea();
    add(new JScrollPane(displayArea));

    setSize(500, 300);//size of JFrame
    setVisible(true);
}//end constructor

/**
 * code that executes the server obj.  Think of it as FileServer's main().  This is called from main().
 */
public void runServer() {
    try {
        ss = new ServerSocket(portNum, 100); //creates server socket with port # specified by user and a queue of 100
        while (true) { //infinite loop to continually listen for client connections
            try {
                waitForConnection(); //wait for client connections
                getStreams(); //get I/O streams
                processConnection(); 
            }
            catch (EOFException e) {
                e.printStackTrace();
            }
            finally {
                closeConnection();
            }
        }
    }
    catch (IOException e) {
        e.printStackTrace();
    }
}//end runServer

/**
 * creates socket obj to interact with client.  Socket created when connection with client made
 * @throws IOException 
 */
public void waitForConnection() throws IOException {
    displayMessage("Waiting for connection\n");
    connection = ss.accept(); //returns socket obj when connection made with client
    displayMessage("Connection made with " + connection.getInetAddress().getHostName());
}//end waitForConnection

/**
 * gets IO stream objs for FileServer class
 */
public void getStreams() {
    try {
        oos = new ObjectOutputStream(connection.getOutputStream());
        oos.flush();
        ois = new ObjectInputStream(connection.getInputStream());
    }
    catch (IOException e) {
        e.printStackTrace();
    }
    displayMessage("\n Got both IO streams \n");
}//end getStreams

/**
 * receives filename sent from client and creates file
 */
public void processConnection() throws IOException {
    sendData("Connection successful");
    setTextFieldEditable(true);
    do { //added do while for testing
        try {
            String message = (String) ois.readObject(); //should read in filename then create file obj
            displayMessage("\n " + message + " received from client\n");
            displayMessage("Type in absolute path of file in text field above");
            file = new File(message);
            if(!file.exists()) {
                sendData("File not found");
            }
            else {
                Scanner cin = new Scanner(file);
                while(cin.hasNextLine()) {
                    message = cin.nextLine();
                    sendData(message);
                }
                cin.close();
            }

        }
        catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    } while(true);
}//end processConnection

/**
 * closes IO streams
 */
public void closeConnection() throws IOException {
    displayMessage("\nClosing connections\n");
    setTextFieldEditable(false); 
    oos.close();
    ois.close();
    connection.close();
}//end closeConnection

/**
 * sends message to client
 * @param message
 */
public void sendData(String message) {
    try{
        oos.writeObject(message);//this is what sends message
        oos.flush();
        displayMessage("\n in sendData: " + message + "\n");
    }
    catch(IOException e) {
        displayArea.append("\n Error writing object");
        e.printStackTrace();
    }
}//end sendData

public void displayMessage(final String message) {
    SwingUtilities.invokeLater(
            new Runnable() {
                public void run() {
                    displayArea.append(message);
                }
            });//end SwingUtilties
}

private void setTextFieldEditable( final boolean editable )
   {
      SwingUtilities.invokeLater(
         new Runnable() 
         {
            public void run() // sets enterField's editability
            {
               field.setEditable( editable );
            } // end method run
         } // end anonymous inner class
      ); // end call to SwingUtilities.invokeLater
   } // end method setTextFieldEditable

}

客户代码

import java.io.EOFException;
import java.io.File;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

public class FileClient extends JFrame 
{
    public static void main(String[] args) {
    int port = Integer.parseInt(args[0]);
    String fileName = args[1]; //must use absolute path for filename
    FileClient app = new FileClient("127.0.0.1", port, fileName);
    app.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    app.runClient();
}

 private JTextField enterField; // enters information from user
 private JTextArea displayArea; // display information to user
 private ObjectOutputStream output; // output stream to server
 private ObjectInputStream input; // input stream from server
private String message = ""; // message from server
private String chatServer; // host server for this application
private Socket client; // socket to communicate with server
private int portNum;
private String fileName;
private File file;

// initialize chatServer and set up GUI
public FileClient( String host, int port, String fileName )
{
  super( "Client" );
  portNum = port;
  this.fileName = fileName;
  //file = new File(fileName);
  chatServer = host; // set server to which this client connectsS

  enterField = new JTextField(); // create enterField
  enterField.setEditable( false );
  enterField.addActionListener( //need to find a way to send fileName to server without having to type it in
     new ActionListener() 
     {
        // send message to server
        public void actionPerformed( ActionEvent event )
        {
           sendData( event.getActionCommand() );
           enterField.setText( "Messages will be displayed in other text box" );
        } // end method actionPerformed
     } // end anonymous inner class
  ); // end call to addActionListener

  add( enterField, BorderLayout.NORTH );

  displayArea = new JTextArea(); // create displayArea
  add( new JScrollPane( displayArea ), BorderLayout.CENTER );

  setSize( 500, 300 ); // set size of window
  setVisible( true ); // show window
} // end Client constructor

// connect to server and process messages from server
public void runClient() 
{
  try // connect to server, get streams, process connection
  {
     connectToServer(); // create a Socket to make connection
     getStreams(); // get the input and output streams
     processConnection(); // process connection
     sendData(fileName); //sends name of file to server to retrieve
     displayMessage("Sent request for " + fileName + " to server.");
  } // end try
  catch ( EOFException eofException ) 
  {
     displayMessage( "\nClient terminated connection" );
  } // end catch
  catch ( IOException ioException ) 
  {
     ioException.printStackTrace();
  } // end catch
  finally 
  {
     closeConnection(); // close connection
  } // end finally
} // end method runClient

// connect to server
private void connectToServer() throws IOException
{      
  displayMessage( "Attempting connection\n" ); //not getting here

  // create Socket to make connection to server
  client = new Socket( InetAddress.getByName( chatServer ), portNum );

  // display connection information
  displayMessage( "Connected to: " + 
     client.getInetAddress().getHostName() );
} // end method connectToServer

// get streams to send and receive data
private void getStreams() throws IOException
{
  // set up output stream for objects
  output = new ObjectOutputStream( client.getOutputStream() );      
  output.flush(); // flush output buffer to send header information

  // set up input stream for objects
  input = new ObjectInputStream( client.getInputStream() );

  displayMessage( "\nGot I/O streams\n" );
 } // end method getStreams

 // process connection with server
 private void processConnection() throws IOException //problem possibly due to processConnection being in infinite loop?
{
  // enable enterField so client user can send messages
  setTextFieldEditable( true );

  do // process messages sent from server
  { 
     try // read message and display it
     {
        message = input.readObject().toString(); // read new message
        displayMessage( "\n" + message ); // display message
     } // end try
     catch ( ClassNotFoundException classNotFoundException ) 
     {
        displayMessage( "\nUnknown object type received" );
        classNotFoundException.printStackTrace();
     } // end catch

  } while ( !message.equals( "SERVER>>> TERMINATE" ) );
} // end method processConnection

// close streams and socket
private void closeConnection() 
{
  displayMessage( "\nClosing connection" );
  setTextFieldEditable( false ); // disable enterField

  try 
  {
     output.close(); // close output stream
     input.close(); // close input stream
     client.close(); // close socket
  } // end try
  catch ( IOException ioException ) 
  {
     ioException.printStackTrace();
  } // end catch
} // end method closeConnection

// send message to server
private void sendData( String message ) //need to send filename to server
{
  try // send object to server
  {
     output.writeObject(message);
     //output.writeObject(fileName); //is writeObject the appropriate write method?
     output.flush(); // flush data to output
     displayMessage( "\nCLIENT>>> " + message );
  } // end try
  catch ( IOException ioException )
  {
     displayArea.append( "\nError writing object" );
     ioException.printStackTrace();
  } // end catch
} // end method sendData

// manipulates displayArea in the event-dispatch thread
private void displayMessage( final String messageToDisplay )
{
  SwingUtilities.invokeLater(
     new Runnable()
     {
        public void run() // updates displayArea
        {
           displayArea.append( messageToDisplay );
        } // end method run
     }  // end anonymous inner class
  ); // end call to SwingUtilities.invokeLater
} // end method displayMessage

// manipulates enterField in the event-dispatch thread
private void setTextFieldEditable( final boolean editable )
{
  SwingUtilities.invokeLater(
     new Runnable() 
     {
        public void run() // sets enterField's editability
        {
           enterField.setEditable( editable );
        } // end method run
     } // end anonymous inner class
  ); // end call to SwingUtilities.invokeLater
} // end method setTextFieldEditable
} // end class Client

我希望这会有所帮助。