как да добавя CR и LF към масив, върнат от String.getBytes()

Преминавайки през някакъв мой код за свързване на сокет, забелязах този метод:

public void write(String line) throws IOException, NullPointerException {
    log.fine(line);
    byte[] bytes = line.getBytes();
    outputStream.write(bytes);   // append 13 and 10 here before the write
    outputStream.write(13);
    outputStream.write(10);
    outputStream.flush();

}

и се оказва, че може би въвеждам известна латентност, може би, като пиша реда и след това добавям CR и LF преди промиване.

Ще бъде ли по-ефективно да добавите CR и LF към масива от байтове, което прави само едно извикване на outputStream.write() вместо три извиквания?

Контекстът е базиран на сокет връзка MUD клиент. (Не, SSH не е опция, MUD игрите използват telnet.)

Тъй като не е ArrayList или нещо лесно за работа, не съм сигурен колко голям е масивът, така че не знам индекса на последния елемент. Итериране на Array в нов масив и след това добавяне на CR и LF към следващите елементи? Това изглежда странно. Не съм сигурен как да избегна NullPointerException при добавяне в края на масива.


person Thufir    schedule 15.12.2013    source източник
comment
къде инициализирате outputStream?   -  person M Sach    schedule 15.12.2013
comment
това е телнет връзка на живо, тя е тук: github.com/THUFIR/MudSocketClient/tree /master/src/   -  person Thufir    schedule 15.12.2013
comment
Може би. Предполагам, че в него няма много. Все пак обикновено се опитвам да сглобя пълна линия от изход, преди да извикам нещо, което може да задейства I/O системно повикване.   -  person Martin James    schedule 15.12.2013
comment
Къде е проследяването на стека на изключението? За кой ред се отнася?   -  person JB Nizet    schedule 15.12.2013
comment
Няма изключение, просто питам как да го направя. Как да добавите CR и LF по-ефективно.   -  person Thufir    schedule 15.12.2013
comment
Добре е да правиш както си. Защо бихте получили NPE, когато добавяте към масив?   -  person JB Nizet    schedule 15.12.2013
comment
защото не знам размера на масива и може да пиша в елемент 9, когато размерът на масива е 7. Или нещо подобно.   -  person Thufir    schedule 15.12.2013
comment
Размерът на масива е bytes.length. Така че просто трябва да създадете масив с дължина на размера + 2, да копирате масива в копието и да инициализирате последните 2 байта в \r и \n. Достъпът до невалиден индекс в масив няма да доведе до NPE. Това би хвърлило ArrayIndexOutOfBoundsException.   -  person JB Nizet    schedule 15.12.2013
comment
прав си, имах в предвид грешната грешка.   -  person Thufir    schedule 15.12.2013


Отговори (1)


Ако вашият обект outputStream е на едно ниво BufferedOutputStream, тогава сте добри. Няма повод за притеснение. Въпреки това, дори и да нямате BufferedOutputStream, потоците на сокет винаги са буферирани, мисля.

За да отговорите на въпроса си, можете да направите нещо подобно:

byte[] msg = line.getBytes(Charset.forName("UTF-8"));
byte[] output = new byte[msg.length + 2];
System.arraycopy(msg, 0, output, 0, msg.length);
output[msg.length] = (byte) 13;
output[msg.length] = (byte) 10;
outputStream.write(output);

Или още по-добре би било:

byte[] msg = line.concat("\r\n").getBytes(Charset.forName("UTF-8"));
outputStream.write(msg);
person Martijn Courteaux    schedule 15.12.2013
comment
добре, това е интересно. Това не е BufferedOutputStream, но ще го разгледам. - person Thufir; 15.12.2013
comment
това изглежда добре, знаех за това, но никога не бях използвал arraycopy, така че не ми хрумна. благодаря, нека опитам. - person Thufir; 15.12.2013
comment
Може ли някой друг да потвърди факта, че потоците на Socket са буферирани на по-ниско ниво? - person Martijn Courteaux; 15.12.2013
comment
Не мисля така, защото трябва да преминете през допълнителни стъпки, за да получите буфериран поток. От Socket можете директно да получите само OutputStream, който можете да след това буферирате. Може би в случая OutputStream трябва да бъде буфериран по подразбиране. Java е изцяло от тези видове наследени проблеми с API, IMHO. Благодаря за хубавия начин за копиране на масиви отново. - person Thufir; 15.12.2013
comment
Фактът, че сокетът има изходен поток, не означава, че не е буфериран. OutputStream е само абстрактен клас. Може да има каквато и да е реализация на буфера, за която се сетите. - person Martijn Courteaux; 15.12.2013
comment
stackoverflow.com/questions/11373259/ - person Martijn Courteaux; 15.12.2013