java - 向客户端发送文件时出现棘手的 NullPointerException

标签 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 引用!

客户端.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);
        }
    }

}

服务器.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;
     }
}

提前致谢!

最佳答案

您永远不会在 Protocol 中初始化 lns,因此它始终是一个 null 引用。您只需将声明更改为:

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

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

您还应该考虑给它一个更易读的名称 - 它是否意味着代表线条?如果是这样,请将其称为lines!

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

关于java - 向客户端发送文件时出现棘手的 NullPointerException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21443892/

相关文章:

java - 正则表达式 - 允许输入键 (java)

java - 使用 Optional wrapper 对多个条件进行 OR

php - Eclipse Subversion Plugin Subclipse 显示错误

javascript - 是 PHP include() 还是 JS src 更快地包含文件?

java - Android 适配器因 ArrayIndexOutOfBoundsException 崩溃

python - PyDev 中假的 Unresolved 导入错误

java - eclipse 是否带有内置包 javax.sound.sampled.* ?

facebook - 在服务器端生成具有某些效果的电影,例如 Facebook 回顾

node.js - 服务器端应用程序的可扩展性,最佳方法

java - 如何在Java中从文件中读取特定单词后的int