将文件发送到客户端时Tricky NullPointerException

时间:2014-01-29 22:20:10

标签: java eclipse server-side

我正在使用Java中的一个简单服务器,它应该具有跨计算机传输文件的能力。我在Protocol.class的第77行得到NullPointerException。这是堆栈:

java.lang.NullPointerException
       at Protocol.processInput(Protocol.java:77)
       at Server.main(Server.java:41)

为什么会这样?第77行没有null个引用!

Client.java:

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;

import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.filechooser.FileNameExtensionFilter;


public class Client {

    private static boolean filein = false;
    private static ArrayList<String> fln = new ArrayList<>();

    public static void main(String[] args) throws IOException {

        if (args.length != 2) {
            System.err.println(
                "Usage: java Client <host name> <port number>");
            System.exit(1);
        }

        String hostName = args[0];
        int portNumber = Integer.parseInt(args[1]);

        try (
            Socket kkSocket = new Socket(hostName, portNumber);
            PrintWriter out = new PrintWriter(kkSocket.getOutputStream(), true);
            BufferedReader in = new BufferedReader(
                new InputStreamReader(kkSocket.getInputStream()));
        ) {
            BufferedReader stdIn =
                new BufferedReader(new InputStreamReader(System.in));
            String fromServer;
            String fromUser = null;

            while ((fromServer = in.readLine()) != null) {
                System.out.println("Server: " + fromServer);
                if (fromServer.equals("@file")) { filein = true; 
                fromUser = "";}
                else if(fromServer.equals("@end@")) {

                    filein = false;
                    JFileChooser chooser = new JFileChooser();
                    int returnVal = chooser.showSaveDialog(null);
                    if(returnVal == JFileChooser.APPROVE_OPTION) {
                           String fname = chooser.getSelectedFile().getAbsolutePath();
                           File f = new File(fname);
                           f.createNewFile();
                           PrintWriter p = new PrintWriter(f);
                           for(int i = 0; i < fln.size(); i++) {

                               p.println(fln.get(i));

                           }

                           p.close();
                           JOptionPane.showMessageDialog(null, "File saved!");
                    }


                }
                else if (filein == true) {

                    fln.add(fromServer);
                    System.out.println(fln.get(fln.size() - 1));

                }
                if (fromServer.equals("Bye."))
                    break;

                if (!filein) fromUser = stdIn.readLine();
                else if (filein) fromUser = "@contintueFileRun";
                if (fromUser != null) {
                    System.out.println("Client: " + fromUser);
                    out.println(fromUser);
                }
            }
        } catch (UnknownHostException e) {
            System.err.println("Don't know about host " + hostName);
            System.exit(1);
        } catch (IOException e) {
            System.err.println("Couldn't get I/O for the connection to " +
                hostName);
            System.exit(1);
        }
    }

}

Server.java:

import java.io.*;
import java.net.*;

import static java.lang.System.out;

/**
 * Title: FTP Server
 * @author Galen Nare
 * @version 1.0
 */

public class Server {
    public static void main(String[] args) throws IOException {

        out.println("Starting server!");

        if (args.length != 1) {
            System.err.println("Usage: java Server <port number>");
            System.exit(1);
        }

        int portNumber = Integer.parseInt(args[0]);

        try ( 
            ServerSocket serverSocket = new ServerSocket(portNumber);
            Socket clientSocket = serverSocket.accept();
            PrintWriter out =
                new PrintWriter(clientSocket.getOutputStream(), true);
            BufferedReader in = new BufferedReader(
                new InputStreamReader(clientSocket.getInputStream()));
        ) {

            String inputLine, outputLine;

            // Initiate conversation with client
            Protocol kkp = new Protocol();
            outputLine = kkp.processInput("");
            out.println(outputLine);

            while ((inputLine = in.readLine()) != null) {
                outputLine = kkp.processInput(inputLine);
                out.println(outputLine);
                if (outputLine.equals("Bye."))
                    break;
            }
        } catch (IOException e) {
            System.out.println("Exception caught when trying to listen on port "
                + portNumber + " or listening for a connection");
            System.out.println(e.getMessage());
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

最后,Protocol.java:

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Scanner;

public class Protocol {

    enum ServerState {

        STARTING,
        WAITING

    }  

    ArrayList<String> lns;

    boolean fileout = false;
    int i = 0;

        private ServerState state = ServerState.STARTING;

        public String processInput(String theInput) throws Exception {
            String theOutput = "";

            if (state == ServerState.STARTING) {
                theOutput = "Hello, Client!";
                state = ServerState.WAITING;
            }

            if (!theInput.equals("")) {
                if(theInput.length() > 10 && theInput.startsWith("e")) {
                if (theInput.substring(0,11).equalsIgnoreCase("executecmd ")) {
                theOutput = theInput.substring(11);
                System.out.println(theOutput);
                 try {
                    @SuppressWarnings("unused")

                    Process child = Runtime.getRuntime().exec(theInput.substring(11));
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                theOutput = "Executed " + theInput.substring(11) + ".";
                }
            } else if (theInput.equalsIgnoreCase("stop")) {

                theOutput = "Stopping Server!";
                System.exit(0);

            } else if (theInput.equalsIgnoreCase("executecmd")) {

                theOutput = "Usage: executecmd <command [-options]>";


            } else if (theInput.equalsIgnoreCase("getfile")) {

                theOutput = "Usage: getfile <file>";

            } else if(theInput.length() > 7 && theInput.startsWith("g")) {
                System.out.println("in");
                if (theInput.substring(0,8).equalsIgnoreCase("getfile ")) {
                theOutput = theInput.substring(8);
                File f = new File(theInput.substring(8));
                Scanner scan = new Scanner(f);
                ArrayList<String> lns = new ArrayList<>();
                while(scan.hasNext()) {
                    lns.add(scan.nextLine());
                }
                for (int i=0; i < lns.size(); i++) {
                    System.out.println(lns.get(i));
                }
                scan.close();
                lns.add("@end@");
                theOutput = "@file";
                fileout = true;
                }
            } else if (fileout && i < lns.size()) {

                    theOutput = lns.get(i);
                    i++;

            } else if (fileout && i == lns.size()) {

                i = 0;
                fileout = false;

            } else {


                theOutput = "That is not a command!";

            }


            }
            System.out.print(theOutput);
            return theOutput;
     }
}

提前致谢!

1 个答案:

答案 0 :(得分:4)

您永远不会在lns中初始化Protocol,因此它始终是null引用。您可以通过将声明更改为:

来逃脱
private List<String> lns = new ArrayList<String>();

(我已将其设为私有,并且只是出于习惯而将类型更改为List ...)

你还应该考虑给它一个更易读的名字 - 它是否代表线条?如果是,请将其命名为lines

(接下来,考虑一下你自己无法诊断的原因。你是否在调试器中单步执行此操作?为什么你认为第77行没有空引用?你在添加方面采取了哪些诊断步骤?额外的记录等?使用这样的错误作为学习经验来使未来的问题更容易处理是很重要的。)