AS3, как показать только последнюю строку динамического текста (и не только)? - PullRequest
1 голос
/ 28 июля 2010

Я создал код действия, который загружает внешний текстовый файл и прокручивает его содержимое до конца:

var myTextLoader:URLLoader = new URLLoader();
myTextLoader.addEventListener(Event.COMPLETE, onLoaded);

function onLoaded(e:Event):void {
track_info.text = e.target.data;

addChild(track_info);
  addEventListener(Event.ENTER_FRAME, scrollField);
}

function scrollField(e:Event):void {
 if(track_info.scrollV < track_info.maxScrollV) {
    track_info.scrollV++;
  }else{
removeEventListener(Event.ENTER_FRAME, scrollField);
  }
}

myTextLoader.load(new URLRequest("tracks.txt"));

track.txt - это файл журнала из программного обеспечения, которое извлекает теги mp3 исполнителя и названия песни из проигрывателя в режиме реального времени в этом формате (его нельзя изменить). Текущая песня находится внизу списка. Каждая песня начинается с «[День-Месяц-Год-Час: Мин: Сек] *» (префикс 25 символов):

[14-07-2010 20:21:33] Log file created for client.
[14-07-2010 20:21:33] Client connected.
[14-07-2010 20:26:21] * Artist 21 - Song 11
[14-07-2010 20:40:02] * Artist 42 - Song 02
[14-07-2010 20:45:04] * Artist 14 - Song 10
[14-07-2010 20:47:19] * Artist 46 - Song 04
[14-07-2010 20:51:09] * Artist 07 - Song 09
[14-07-2010 20:54:13] * Artist 54 - Song 01
[14-07-2010 20:57:32] * Artist 19 - Song 12
[14-07-2010 21:00:51] * Artist 35 - Song 06
[14-07-2010 21:04:02] * Artist 43 - Song 08

Сценарий работает, но я хотел бы знать, можно ли решить эту проблему:

  1. Я хотел бы показать во флэш-фильме только текущую песню, последнюю строку списка (ту, которая воспроизводится), а не все данные в файле track.txt. Можно ли это сделать?

  2. Для этого фильм должен автоматически обновлять содержимое из .txt почти в реальном времени, чтобы показать новую информацию о песне в текстовом поле, заменив предыдущую. Есть ли способ сделать это?

  3. Наконец, возможно ли скрыть префикс «[Day-Month-Year Hour: Min: Sec] *» в текстовом поле, чтобы отображать только раздел «Исполнитель - Название песни» во флэш-фильме?

Заранее благодарен за помощь.

Редактировать

var reload:Timer = new Timer(5000, 0); 
reload.addEventListener(TimerEvent.TIMER, onTimer); 
function onTimer(event:TimerEvent):void{ 
    var myTextLoader:URLLoader = new URLLoader(); 
    myTextLoader.addEventListener(Event.COMPLETE, onLoaded); 
    function onLoaded(e:Event):void {
        var lines:Array = e.target.data.split("\n"); 
        var lastLine:String = lines[lines.length - 1]; 
        var artistAndSong:String = lastLine.substr(24); 
        track_info.text = artistAndSong; 
        addChild(track_info); 
        myTextLoader.load(new URLRequest("tracks.txt")); 
    } 
    reload.start(); 
}

Редактировать

Возможно, split () не работает с реальным файлом .log. Весь текст показан, а не только последняя строка. Вот пример .log:

[30-07-2010 03:21:34] Log file created for client "127.0.0.1,55684".
[30-07-2010 03:21:34] Client "127.0.0.1,55684" connected and has been identified as Traktor (or a something close enough).
[30-07-2010 03:22:58] * The Bravery - An Honest Mistake
[30-07-2010 03:23:22] * The Waterboys - The Whole of the Moon

Редактировать

var reload:Timer = new Timer(5000, 1); 
reload.addEventListener(TimerEvent.TIMER, onTimer); 

var tracksLoader:URLLoader = new URLLoader();
tracksLoader.addEventListener(Event.COMPLETE,onTracksLoaded);
tracksLoader.addEventListener(IOErrorEvent.IO_ERROR,onTracksError);
tracksLoader.addEventListener(SecurityErrorEvent.SECURITY_ERROR,onTracksError);

loadTracks();

function onTracksLoaded(e:Event):void {
    trace("onTracksLoaded");
    parseTracks(tracksLoader.data); 
    reload.start(); 
}

function onTimer(event:TimerEvent):void{ 
    loadTracks();
}

function onTracksError(e:Event):void {
    trace("onTracksError", e);
    reload.start();
}

function loadTracks():void {
    tracksLoader.load(new URLRequest("127.0.0.1,55684.log")); 
}

function parseTracks(data:String):void {
    try {
        debugChars(data); 
        var lines:Array = data.split("\r\n"); 
        var lastLine:String = lines[lines.length - 1]; 
        var artistAndSong:String = lastLine.substr(24).split(" - ").join("\n");
        trace(artistAndSong);
        track_info.text = artistAndSong; 
        addChild(track_info);
    } catch(e:Error) {

    }
}

function debugChars(str:String):void {
    var buffer:ByteArray = new ByteArray();
    buffer.writeUTFBytes(str);
    buffer.position = 0;
    var result:String = "";
    while(buffer.bytesAvailable) {
        result += "0x" + uint(buffer.readUnsignedByte()).toString(16) + ", ";
        if(buffer.position % 16 == 0) {
            result += "\n";
        }

    }
    //  print this string...
    trace(result);
}

Редактировать

Обратите внимание, что разрывы строки между «Artist» и «Song Name» связаны с этим кодом:

.split(" - ").join("\n");

.log на самом деле поставляется с «Artist - Song Name».

onTracksLoaded
0x5b, 0x33, 0x30, 0x2d, 0x30, 0x37, 0x2d, 0x32, 0x30, 0x31, 0x30, 0x20, 0x30, 0x33, 0x3a, 0x32, 
0x31, 0x3a, 0x33, 0x34, 0x5d, 0x20, 0x4c, 0x6f, 0x67, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x63, 
0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x63, 0x6c, 0x69, 0x65, 0x6e, 
0x74, 0x20, 0x22, 0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x2c, 0x35, 0x35, 0x36, 
0x38, 0x34, 0x22, 0x2e, 0xa, 0x5b, 0x33, 0x30, 0x2d, 0x30, 0x37, 0x2d, 0x32, 0x30, 0x31, 0x30, 
0x20, 0x30, 0x33, 0x3a, 0x32, 0x31, 0x3a, 0x33, 0x34, 0x5d, 0x20, 0x43, 0x6c, 0x69, 0x65, 0x6e, 
0x74, 0x20, 0x22, 0x31, 0x32, 0x37, 0x2e, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x2c, 0x35, 0x35, 0x36, 
0x38, 0x34, 0x22, 0x20, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x20, 0x61, 0x6e, 
0x64, 0x20, 0x68, 0x61, 0x73, 0x20, 0x62, 0x65, 0x65, 0x6e, 0x20, 0x69, 0x64, 0x65, 0x6e, 0x74, 
0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x61, 0x73, 0x20, 0x54, 0x72, 0x61, 0x6b, 0x74, 0x6f, 0x72, 
0x20, 0x28, 0x6f, 0x72, 0x20, 0x61, 0x20, 0x73, 0x6f, 0x6d, 0x65, 0x74, 0x68, 0x69, 0x6e, 0x67, 
0x20, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x20, 0x65, 0x6e, 0x6f, 0x75, 0x67, 0x68, 0x29, 0x2e, 0xa, 
0x5b, 0x33, 0x30, 0x2d, 0x30, 0x37, 0x2d, 0x32, 0x30, 0x31, 0x30, 0x20, 0x30, 0x33, 0x3a, 0x32, 
0x32, 0x3a, 0x35, 0x38, 0x5d, 0x20, 0x2a, 0x20, 0x54, 0x68, 0x65, 0x20, 0x42, 0x72, 0x61, 0x76, 
0x65, 0x72, 0x79, 0x20, 0x2d, 0x20, 0x41, 0x6e, 0x20, 0x48, 0x6f, 0x6e, 0x65, 0x73, 0x74, 0x20, 
0x4d, 0x69, 0x73, 0x74, 0x61, 0x6b, 0x65, 0xa, 0x5b, 0x33, 0x30, 0x2d, 0x30, 0x37, 0x2d, 0x32, 
0x30, 0x31, 0x30, 0x20, 0x30, 0x33, 0x3a, 0x32, 0x33, 0x3a, 0x32, 0x32, 0x5d, 0x20, 0x2a, 0x20, 
0x54, 0x68, 0x65, 0x20, 0x57, 0x61, 0x74, 0x65, 0x72, 0x62, 0x6f, 0x79, 0x73, 0x20, 0x2d, 0x20, 
0x54, 0x68, 0x65, 0x20, 0x57, 0x68, 0x6f, 0x6c, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 
0x20, 0x4d, 0x6f, 0x6f, 0x6e, 0xa, 0x5b, 0x33, 0x30, 0x2d, 0x30, 0x37, 0x2d, 0x32, 0x30, 0x31, 
0x30, 0x20, 0x30, 0x33, 0x3a, 0x32, 0x37, 0x3a, 0x35, 0x36, 0x5d, 0x20, 0x2a, 0x20, 0x42, 0x61, 
0x62, 0x61, 0x73, 0x6f, 0x6e, 0x69, 0x63, 0x6f, 0x73, 0x20, 0x2d, 0x20, 0x59, 0x65, 0x67, 0x75, 
0x61, 0xa, 
g file created for client "127.0.0.1,55684".
[30-07-2010 03:21:34] Client "127.0.0.1,55684" connected and has been identified as Traktor (or a something close enough).
[30-07-2010 03:22:58] * The Bravery
An Honest Mistake
[30-07-2010 03:23:22] * The Waterboys
The Whole of the Moon
[30-07-2010 03:27:56] * Babasonicos
Yegua

Ответы [ 2 ]

3 голосов
/ 28 июля 2010

Для 1) и 3), String :: split сделает это.

Это было бы что-то вроде:

/* 
\n is the end of line character. Depending on the program that creates
the text file, you might need to change it to \r\n or \r
Note I'm not doing any error checking, you might want to add it...
*/
var lines:Array = e.target.data.split("\n");
var lastLine:String = lines[lines.length - 1];

Если формат фиксированный, вы можете разделить последнюю строку на «*» или даже использовать substr , чтобы получить имя исполнителя и название песни.

/*
Again, I'm not checking for any errors
*/
var songAndArtist:String = lastLine.split("*")[1];

или

var songAndArtist:String = lastLine.substr(25);

Для 2) просто опросите сервер с разумным интервалом. Есть несколько способов сделать это. При загрузке файла можно запустить Timer ; когда этот таймер завершится, остановите таймер и перезагрузите файл. Вы также можете использовать setTimeout вместо таймера.

Редактировать

Не уверен, в чем заключалась ваша проблема с кодом, который вы разместили, но часть, которая анализирует журнал, прекрасно работает для меня. Я немного переупорядочил его и добавил проверки на ошибки при загрузке данных.

Одна проблема с вашим кодом: вы вызываете таймер, прежде чем дождаться завершения текущей операции загрузки. Это может привести к проблемам. Вам не нужно иметь две загрузки одновременно, поэтому лучше дождаться завершения загрузки (успешно или нет), прежде чем пытаться перезагрузить компьютер (возможно, вы не захотите пытаться перезагрузить компьютер в случае ошибки или, возможно, ограничите повторяет до 2, 3 или что-то подобное, но это на ваше усмотрение).

Кроме того, обратите внимание, что я изменил счетчик повторений таймера на 1, так что вам не нужно его останавливать. Это означает, что он будет запущен один раз, а затем остановится, пока вы не вызовете start снова). Я немного структурировал ваш код, чтобы разделить его части на разные функции, чтобы было легче следовать.

В функции parseTracks я завернул весь код в try / catch, который перехватывает почти все ошибки. Это довольно быстро и грязно, поэтому я, как правило, не рекомендую такой стиль обработки ошибок, но могу выполнить эту работу здесь.

var reload:Timer = new Timer(5000, 1); 
reload.addEventListener(TimerEvent.TIMER, onTimer); 

var tracksLoader:URLLoader = new URLLoader();
tracksLoader.addEventListener(Event.COMPLETE,onTracksLoaded);
tracksLoader.addEventListener(IOErrorEvent.IO_ERROR,onTracksError);
tracksLoader.addEventListener(SecurityErrorEvent.SECURITY_ERROR,onTracksError);

loadTracks();

function onTracksLoaded(e:Event):void {
    trace("onTracksLoaded");
    parseTracks(tracksLoader.data); 
    reload.start(); 
}

function onTimer(event:TimerEvent):void{ 
    loadTracks();
}

function onTracksError(e:Event):void {
    trace("onTracksError", e);
    reload.start();
}

function loadTracks():void {
    tracksLoader.load(new URLRequest("tracks.txt")); 
}

function parseTracks(data:String):void {
    try {
        var lines:Array = data.split("\n"); 
        var lastLine:String = lines[lines.length - 1]; 
        var artistAndSong:String = lastLine.substr(24); 
        trace(artistAndSong);
    } catch(e:Error) {

    }
}

Редактировать 2

Добавьте эту функцию и напечатайте ее результат, чтобы попытаться определить, есть ли какая-то проблема с задействованными символами ... Вызовите ее из parseTracks следующим образом:

debugChars(data);


function debugChars(str:String):void {
    var buffer:ByteArray = new ByteArray();
    buffer.writeUTFBytes(str);
    buffer.position = 0;
    var result:String = "";
    while(buffer.bytesAvailable) {
        result += "0x" + uint(buffer.readUnsignedByte()).toString(16) + ", ";
        if(buffer.position % 16 == 0) {
            result += "\n";
        }

    }
    //  print this string...
    trace(result);
}
1 голос
/ 28 июля 2010

вместо разделения строки я бы предложил совпадение строк с некоторыми регулярными выражениями

var $lastLine:String = String(e.target.data).match(/.*$/);

Вы также можете получить последнюю строку минус что угодно в скобках [^]]*$ - но это может затормозить, если у артиста есть ] в имени, но я бы все равно использовал выражение, чтобы получить художника из $lastLine

тогда вы можете использовать

var $artistAndSong:String = $lastLine.match(/\*.*/);

это будет соответствовать чему-либо после (включая) первого *

если вы играете с regex немного больше, вы можете извлечь из этого немало полезного, но всегда помогите использовать что-то вроде http://regexpal.com/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...