繁体   English   中英

java.lang.ArrayIndexOutOfBoundsException真的很奇怪

[英]java.lang.ArrayIndexOutOfBoundsException really weird

我知道我在日志猫中遇到的异常的名称非常正确。 我唯一的问题是我无法确定导致我异常的原因。 我创建了PC-Android多客户端聊天。

PC版本可与服务器和客户端100%兼容。 我实现了从PC客户端到android客户端以及聊天WORKS的相同技术。

我得到的唯一问题是,当我与android连接时,clientArea(跟踪所有连接的用户)不是跟踪其他名称,而是跟踪android客户端用户名的倍数。 即。 我只在Android上使用用户名:Jurko进行连接,clientArea会有2个叫Jurko的人,而不是只有一个。

Logcat:

10-11 17:19:08.221: ERROR/AndroidRuntime(12379): FATAL EXCEPTION: main
        java.lang.ArrayIndexOutOfBoundsException: length=2; index=2
        at com.example.JurkoAndroidChat.MyActivity$ServerTask.onProgressUpdate(MyActivity.java:175)
        at com.example.JurkoAndroidChat.MyActivity$ServerTask.onProgressUpdate(MyActivity.java:130)
        at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:647)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:137)
        at android.app.ActivityThread.main(ActivityThread.java:4895)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:511)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:994)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:761)
        at dalvik.system.NativeStart.main(Native Method)

Android客户端:

package com.example.JurkoAndroidChat;

import android.app.Activity;
import android.content.DialogInterface;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.view.View;

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



public class MyActivity extends Activity {
    /**
     * Called when the activity is first created.
     */
    // Right here, we connecting the components of the main.xml form to code
    Button connectButton, disconnectButton, sendButton;
    TextView chatArea, clientArea;
    EditText messageField, usernameField, ipField;

    //Extra variables and sockets
    String username, serverIP;
    int Port = 5000;
    Socket sock;
    PrintWriter out;
    BufferedReader in;
    ArrayList<String> userList = new ArrayList();
    Boolean isConnected = false, exceptionCaught = false;

    ServerTask serverTask;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        System.out.println("Working?");
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        connectButton = (Button)findViewById(R.id.button);
        sendButton = (Button)findViewById(R.id.button1);
        disconnectButton = (Button)findViewById(R.id.button2);

        chatArea = (TextView)findViewById(R.id.textView2);
        clientArea = (TextView)findViewById(R.id.textView3);

        messageField = (EditText)findViewById(R.id.editText2);
        usernameField = (EditText)findViewById(R.id.editText);
        ipField = (EditText)findViewById(R.id.editText1);



        connectButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //To change body of implemented methods use File | Settings | File Templates.
                if (isConnected == false) {
                    username = usernameField.getText().toString();
                    usernameField.setFocusable(false);
                    usernameField.setClickable(false);
                    serverIP = ipField.getText().toString();
                    ipField.setFocusable(false);
                    ipField.setClickable(false);
                    serverTask = new ServerTask();
                    serverTask.execute();


                } else if (isConnected == true) {
                    chatArea.append("You are already connected to the server.\n");
                }
            }
        });

        disconnectButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //To change body of implemented methods use File | Settings | File Templates.
                String bye = (username + "µ µDisconnect");
                try {
                    out.print(bye);
                    out.flush();
                    chatArea.append("Disconnected.\n");
                    sock.close();

                } catch (Exception e) {  } // nothing caught so far.
                isConnected = false;
                usernameField.setFocusable(true);
                usernameField.setClickable(true);
                usernameField.setFocusableInTouchMode(true);
                ipField.setFocusable(true);
                ipField.setFocusableInTouchMode(true);
                ipField.setClickable(true);
                clientArea.setText("");

            }
        });

        sendButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //To change body of implemented methods use File | Settings | File Templates.
                String nothing = "";
                if ((messageField.getText().toString().equals(nothing))) {
                    messageField.setText("");
                    messageField.requestFocus();
                } else {
                    try {
                        out.println(username + "µ" + messageField.getText().toString() + "µ" + "Chat");
                        out.flush();


                    } catch (Exception e) {
                        Log.e("Error", e.toString());
                        chatArea.append("Message was not sent.\n" + e);
                    }
                    messageField.setText("");
                    messageField.requestFocus();
                }
            }
        });

    }


    public class ServerTask extends AsyncTask<Void, Void, Void> {

        String[] data;
        String stream, done = "Done", connect = "Connect", disconnect = "Disconnect", chat = "Chat";
        @Override
        protected Void doInBackground(Void... voids) {
            try {
                Log.i("Asynctask", "doInBackground");
                sock = new Socket(serverIP, Port);
                out = new PrintWriter(sock.getOutputStream());
                in = new BufferedReader(new InputStreamReader(sock.getInputStream()));
                out.println(username + "µ" + "has connected." + "µ" + "Connect");
                out.flush();
                isConnected = true;


            } catch (Exception ex) {
                    exceptionCaught = true;
                Log.e("Application", ex.toString());

            }
            try {
                while ((stream = in.readLine()) != null) {

                    publishProgress();
                }
            } catch (Exception e) {}

            return null;
        }

        public void writeUsers() {
            clientArea.setText("");
            Iterator<String> iterator = userList.iterator();
            while (iterator.hasNext()) {
                String token = iterator.next();
                clientArea.append(token + '\n');
            }
        }

        @Override
        protected void onProgressUpdate(Void... values) {

                    data = stream.split("µ");

                    if (data[2].equals(chat)) {
                        if (data[1].equals("has connected.") || data[1].equals("has disconnected."))
                            chatArea.append(data[0] + " " + data[1] + '\n');
                        else
                            chatArea.append(data[0] + ": " + data[1] + '\n');
                    } else if (data[2].equals(connect)) {
                        userList.add(data[0]);
                        writeUsers();
                    } else if (data[2].equals(disconnect)) {
                        userList.remove(data[0]);
                        writeUsers();
                    } else if (data[2].equals(done))
                        userList.clear();

           }

        @Override
        protected void onPostExecute(Void aVoid) {
            super.onPostExecute(aVoid);
            if (exceptionCaught == true) {
                chatArea.append("Unable to connect to " + serverIP + " at port " + Port + ".\n");
                usernameField.setFocusable(true);
                usernameField.setClickable(true);
                usernameField.setFocusableInTouchMode(true);
                ipField.setFocusableInTouchMode(true);
                ipField.setFocusable(true);
                ipField.setClickable(true);
                exceptionCaught = false;

            }
                //To change body of overridden methods use File | Settings | File Templates.
        }
    }












}

服务器(在PC上):

/*
 * To change this template, choose Tools : Templates
 * and open the template in the editor.
 */

/*
 * ServerWindow.java
 *
 * Created on Apr 23, 2011, 4:16:05 PM
 */


import java.io.*;
import java.net.*;
import java.util.*;
/**
 *
 * @author JurkoGuba
 */
public class ServerWindow extends javax.swing.JFrame {
    ArrayList clientOutputStreams;
    ArrayList<String> onlineUsers;

    public class ClientHandler implements Runnable  {
        BufferedReader reader;
        Socket sock;
        PrintWriter client;


        public ClientHandler(Socket clientSocket, PrintWriter user) {
            // new inputStreamReader and then add it to a BufferedReader
            client = user;
            try {
                sock = clientSocket;
                reader = new BufferedReader(new InputStreamReader(sock.getInputStream()));
            } // end try
            catch (Exception ex) {
                outputPane.append("Error beginning StreamReader. \n");
            } // end catch

        } // end ClientHandler()

        public void run() {
            String message, connect = "Connect", disconnect = "Disconnect", chat = "Chat" ;
            String[] data;

            try {
                while ((message = reader.readLine()) != null) {

                    outputPane.append("Received: " + message + "\n");
                    data = message.split("µ");

                    if (data[2].equals(connect)) {

                        tellEveryone((data[0] + "µ" + data[1] + "µ" + chat));
                        userAdd(data[0]);

                    } else if (data[2].equals(disconnect)) {

                        tellEveryone((data[0] + "µhas disconnected." + "µ" + chat));
                        userRemove(data[0]);

                    } else if (data[2].equals(chat)) {

                        tellEveryone(message);

                    } else {
                        outputPane.append("No Conditions were met. \n");
                    }


                } // end while
            } // end try
            catch (Exception ex) {
                outputPane.append("Lost a connection. \n");
                ex.printStackTrace();
                clientOutputStreams.remove(client);
            } // end catch
        } // end run()
    } // end class ClientHandler
    /** Creates new form ServerWindow */
    public ServerWindow() {
        initComponents();
    }



    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents() {

        jScrollPane1 = new javax.swing.JScrollPane();
        outputPane = new javax.swing.JTextArea();
        startButton = new javax.swing.JButton();
        stopButton = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("House Server");

        outputPane.setColumns(20);
        outputPane.setEditable(false);
        outputPane.setLineWrap(true);
        outputPane.setRows(5);
        outputPane.setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
        jScrollPane1.setViewportView(outputPane);

        startButton.setText("Start");
        startButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                startButtonActionPerformed(evt);
            }
        });

        stopButton.setText("Stop");
        stopButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                stopButtonActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
                layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                        .addGroup(layout.createSequentialGroup()
                                .addContainerGap()
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                        .addGroup(layout.createSequentialGroup()
                                                .addComponent(startButton, javax.swing.GroupLayout.PREFERRED_SIZE, 179, javax.swing.GroupLayout.PREFERRED_SIZE)
                                                .addGap(18, 18, 18)
                                                .addComponent(stopButton, javax.swing.GroupLayout.DEFAULT_SIZE, 183, Short.MAX_VALUE))
                                        .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 380, Short.MAX_VALUE))
                                .addContainerGap())
        );
        layout.setVerticalGroup(
                layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                        .addGroup(layout.createSequentialGroup()
                                .addContainerGap()
                                .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 229, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addGap(18, 18, 18)
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                                        .addComponent(startButton)
                                        .addComponent(stopButton))
                                .addContainerGap(19, Short.MAX_VALUE))
        );

        pack();
    }// </editor-fold>                        

    private void startButtonActionPerformed(java.awt.event.ActionEvent evt) {
        // TODO add your handling code here:
        Thread starter = new Thread(new ServerStart());
        starter.start();

        outputPane.append("Server started. \n");
    }

    private void stopButtonActionPerformed(java.awt.event.ActionEvent evt) {
        // TODO add your handling code here:

        tellEveryone("Serverµis stopping and all users will be disconnected.\nµChat");
        outputPane.append("Server stopping... \n");

    }

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new ServerWindow().setVisible(true);
            }
        });
    }


    public class ServerStart implements Runnable {
        public void run() {
            clientOutputStreams = new ArrayList();
            onlineUsers = new ArrayList();

            try {
                ServerSocket serverSock = new ServerSocket(5000);

                while (true) {
                    // set up the server writer function and then begin at the same
                    // the listener using the Runnable and Thread
                    Socket clientSock = serverSock.accept();
                    PrintWriter writer = new PrintWriter(clientSock.getOutputStream());
                    clientOutputStreams.add(writer);

                    // use a Runnable to start a 'second main method that will run
                    // the listener
                    Thread listener = new Thread(new ClientHandler(clientSock, writer));
                    listener.start();
                    outputPane.append("Got a connection. \n");
                } // end while
            } // end try
            catch (Exception ex)
            {
                outputPane.append("Error making a connection. \n");
            } // end catch

        } // end go()
    }

    public void userAdd (String data) {
        String add = "µ µConnect", done = "Serverµ µDone", name = data;
        outputPane.append("Before " + name + " added. \n");
        onlineUsers.add(name);
        outputPane.append("After " + name + " added. \n");
        tellEveryone(done);

        Iterator<String> iterator = onlineUsers.iterator();
        while (iterator.hasNext()){
             String token = iterator.next();
             tellEveryone(token + add);
        }


    }

    public void userRemove (String user) {
        String add = "µ µDisconnect", done = "Serverµ µDone";
//        Iterator<String> remove = onlineUsers.iterator();
//        while (remove.hasNext()) {
//            String token = remove.next();
//            if (token.equals(user))
//                onlineUsers.remove(token);
//        }
        onlineUsers.remove(user);

        tellEveryone(user + add);
    }

    public void tellEveryone(String message) {
        // sends message to everyone connected to server
        Iterator it = clientOutputStreams.iterator();

        while (it.hasNext()) {
            try {
                PrintWriter writer = (PrintWriter) it.next();
                writer.println(message);
                outputPane.append("Sending: " + message + "\n");
                writer.flush();
                outputPane.setCaretPosition(outputPane.getDocument().getLength());

            } // end try
            catch (Exception ex) {
                outputPane.append("Error telling everyone. \n");
            } // end catch
        } // end while
    } // end tellEveryone()


    // Variables declaration - do not modify                     
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JTextArea outputPane;
    private javax.swing.JButton startButton;
    private javax.swing.JButton stopButton;
    // End of variables declaration                   

}

例外很明显。

java.lang.ArrayIndexOutOfBoundsException: length=2; index=2

告诉您您正在尝试访问长度仅为2 (位置01 )的数组中的index 2位置。

我猜MyActivity.java:175是这一行。

if (data[2].equals(chat)) {

因此,您需要对此进行审查。

data = stream.split("µ");

并检查stream String是否具有预期值(它应至少包含两个µ字符,以组成3个以上的数组)。

让我们从错误消息开始:

java.lang.ArrayIndexOutOfBoundsException: length=2; index=2

我们知道在某个地方您有一个长度为2的数组,但是您已经不知道结尾了,因为在Java数组中索引的范围是0length - 1

可能的解释:

您的data数组通过以下调用初始化:

data = stream.split("µ");

然而,如果没有至少2个µ在字符stream ,那么该阵列会比3更短,并且该线将抛出异常:

if (data[2].equals(connect)) {

在输入这段代码之前,请检查data.length ,以确保其至少为3;否则,请适当地处理错误。

您的stream没有2 µ字符,因此split返回的数组少于3个。 当以下代码尝试使用data[2] ,该元素超出数组的范围,并引发异常。

使您的代码更具防御性,不要总是假设接收到的数据可以。 Vg,拆分后,添加此代码

 if (data.length < 3) {
     // Process error (log, user message, whatever)
     return;
 }

我得出的结论是,不管有人是否遇到与我相同的问题,回答我问题的某些专业人员可能想知道,以便将其添加到那里。

首先,我仔细检查了每条发送的消息都包含2 µs,因此data []的大小不可能小于3。

但是,我在AsyncTask中使用套接字(您必须这样做,或者会得到NetworkTaskOnMainThread异常),在初始化套接字和读取器/写入器之后,在连接套接字时调用publishProgess。 我意识到,通过使用whileLoop,然后基于可能会来回变化的东西(例如,)来调用进度,可能会有些出入。 2个用户同时发送消息。 因此,我将AsyncTask的参数从<Void, Void, Void>更改为<Void, String, Void> ,然后在doInBackground中执行publishProgress时,我将stream作为参数并改为使用该参数。

那似乎解决了问题。 如果有人想触摸它,请做!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM