
com.sta.cts.Scanner Maven / Gradle / Ivy
package com.sta.cts;
import java.util.Hashtable;
import java.io.Reader;
import java.io.InputStream;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import com.sta.mlogger.MLogger;
/**
* Name: Scanner
* Description:
* Die abstrakte Klasse Scanner dient dazu, aus einer Datei (bzw. aus einem
* Stream) zeichenweise zu lesen (getChar, ungetChar), Zeichenfolgen in Token
* umzusetzen (getNewToken) und diese Token zur Verf?gung zu stellen (getToken,
* ungetToken). Der Scanner ist als "passiv" realisiert, das hei?t, er wird (in
* der Regel von einem Parser) aufgerufen. Die Klasse Scanner realisiert das
* Prinzip eines One-Character-Lookahead-Scanners. Ferner wurde ein
* One-Token-Lookahead vorgesehen.
*
* Copyright: Copyright (c) 2001-2004, 2011, 2012, 2016-2019, 2021
* Company: >StA-Soft<
* @author StA
* @version 1.0
*/
public abstract class Scanner implements AutoCloseable
{
/**
* Der Reader, der die Quelldatei (bzw. den Quell-Stream) repr?sentiert.
*/
private Reader myReader;
/**
* ProgressInputStream, falls verwendet, sonst: null.
*/
private ProgressInputStream myPIS = null;
/**
* "myCharBacked" zeigt an, ob ein Zeichen in "myBackedChar" zur?ckgelegt
* wurde.
*/
private boolean myCharBacked;
/**
* "myBackedChar" ist das zur?ckgelegte Zeichen, falls "myCharBacked".
*/
private char myBackedChar;
/**
* "myTokenBacked" zeigt an, ob ein Token in "myBackedToken" zur?ckgelegt
* wurde.
*/
private boolean myTokenBacked;
/**
* "myBackedToken" ist das zur?ckgelegte Token, falls "myTokenBacked".
*/
private Object myBackedToken;
//===========================================================================
/**
* Standard-Constructor: Zur Instantiierung eines Scanners.
*/
public Scanner()
{
init((Reader) null, null);
}
//===========================================================================
/**
* Initialisierung des Scanners mit einem Reader und einem
* ProgressInputStream. Um die korrekte Decodierung der Zeichen muss sich
* der Aufrufer k?mmern.
* @param pReader ein Reader f?r die Quelldatei, oder null
* @param pProgressInputStream ein ProgressInputStream oder null
*/
private void init(Reader pReader, ProgressInputStream pProgressInputStream)
{
myCharBacked = false;
myTokenBacked = false;
myReader = pReader;
myPIS = pProgressInputStream;
}
// Durch die Initialisierung mit einem (Buffered)Reader kann keine
// Zeichenkonvertierung entsprechend dem in der Datei (bzw. im Stream)
// angegebenen Encoding durchgef?hrt werden. Daher sollte auf diese Art der
// Initialisierung verzichtet werden.
/**
* Initialisierung des Scanners mit einem Reader.
* Die Registration des Fortschritts wird dabei nicht (!) initialisiert.
* Um die korrekte Decodierung der Zeichen muss sich der Aufrufer k?mmern.
* @param pReader ein Reader f?r die Quelldatei, oder null
*/
public void init(Reader pReader)
{
init(pReader, null);
}
/**
* Initialisierung des Scanners mit InputStream und Encoding.
* Die Registration des Fortschritts wird dabei ebenfalls initialisiert.
* @param is InputStream
* @param enc Encoding
* @throws IOException im Fehlerfall
*/
public void init(InputStream is, String enc) throws IOException
{
ProgressInputStream pis = new ProgressInputStream(is);
InputStreamReader isr = enc != null ? new InputStreamReader(pis, enc) : new InputStreamReader(pis);
init(new BufferedReader(isr), pis);
}
/**
* Initialisierung des Scanners mit InputStream, Standard-Encoding.
* Die Registration des Fortschritts wird dabei ebenfalls initialisiert.
* @param is InputStream
* @throws IOException im Fehlerfall
*/
public void init(InputStream is) throws IOException
{
init(is, null);
}
/**
* Initialisierung des Scanners mit einem Dateinamen und Encoding.
* Die Registration des Fortschritts wird dabei ebenfalls initialisiert.
* @param pFileName Dateiname der Quelldatei
* @param enc Encoding, Standard: "ISO-8859-1" (falls enc = null)
* @exception IOException falls die Datei nicht gefunden wurde.
*/
public void init(String pFileName, String enc) throws IOException
{
init(new FileInputStream(pFileName), enc);
}
/**
* Initialisierung des Scanners mit einem Dateinamen und dem
* Standard-Encoding.
* Die Registration des Fortschritts wird dabei ebenfalls initialisiert.
* @param pFileName Dateiname der Quelldatei
* @exception IOException falls die Datei nicht gefunden wurde.
*/
public void init(String pFileName) throws IOException
{
init(pFileName, null);
}
//---------------------------------------------------------------------------
/**
* Dateigr??e ermitteln, kann auch 0 sein!
* @return die Dateigr??e
*/
public long getFileSize()
{
return myPIS != null ? myPIS.getFileSize() : 0;
}
/**
* Aktuelle Position in der Datei ermitteln.
* @return aktuelle Position
*/
public long getFilePos()
{
return myPIS != null ? myPIS.getFilePos() : 0;
}
/**
* Liefert einen Anhaltspunkt f?r den Stand der Verarbeitung der Quelldatei.
* @return Prozent der Verarbeitung (0 = Anfang, 100 = Fertig)
*/
public double getProcessIndicator()
{
long fs = getFileSize();
long fp = getFilePos();
if ((fs == 0) || (fp >= fs))
{
return 100;
}
return (((double) fp) * 100 / fs);
}
/**
* Abstrakte Methode zum Setzen von Scanner-Optionen.
* @param pHT Entweder null oder eine initialisierte Hash-Tabelle, die
* als Schl?ssel (Attribut-) Namen (Strings) und als Werte die zugeh?rigen
* Einstellungen/Optionen (Strings) enth?lt.
*/
public abstract void initH(Hashtable pHT);
/**
* Holen eines Zeichens.
* * Wurde ein Zeichen zur?ckgelegt, wird dieses geliefert.
* * Wurde kein Zeichen zur?ckgelegt, wird ein neues gelesen.
* * Konnte kein Zeichen gelesen werden, wird 0x00 geliefert.
* @return Ein gelesenes Zeichen, wie oben beschrieben
* @exception IOException falls ein Lesefehler aufgetreten ist
*/
public char getChar() throws IOException
{
char ch;
if (myCharBacked)
{
myCharBacked = false;
return myBackedChar;
}
else
{
/*
if (myReader.ready())
{
ch = (char) myReader.read();
// myFilePos++;
}
else
{
ch = 0x00;
}
*/
int i = myReader.read();
ch = i < 0 ? 0x00 : (char) i;
return ch;
}
}
/**
* F?r Test-Betrieb: eine getChar-Variante, bei der CRLF ?berlesen wird.
* @return Ein gelesenes Zeichen, wie in getChar() beschrieben, au?er 0x0d
* und 0x0a
* @exception IOException falls ein Dateilesefehler aufgetreten ist
*/
protected char getCharT() throws IOException
{
char ch;
do
{
ch = getChar();
}
while ((ch == 0x0d) || (ch == 0x0a));
return ch;
}
/**
* Zur?cklegen eines Zeichens.
* * Es kann max. 1 Zeichen zur?ckgelegt werden.
* @param ch das zur?ckzulegende Zeichen
*/
public void ungetChar(char ch)
{
if (myCharBacked)
{
MLogger.err("Error (Scanner.ungetChar): Can't \"unget\" more than 1 character.");
// => Exception
}
myCharBacked = true;
myBackedChar = ch;
}
/**
* Holen eines neuen Tokens.
* * Abstrakte Methode, mu? ?berschrieben werden.
* * Ein Token ist ein Object.
* * Ein Fehler (z. B. Dateiende) wird durch das Ergebnis "null" gekennzeichnet.
* @return gibt ein Token oder null zur?ck
*/
public abstract Object getNewToken();
/**
* Holen eines Tokens.
* * Wurde ein Token zur?ckgelegt, wird dieses geliefert.
* * Wurde kein Token zur?ckgelegt, wird ein neues gelesen (getNewToken) und zur?ckgeliefert.
* @return ein Token, wie oben beschrieben
*/
public Object getToken()
{
if (myTokenBacked)
{
myTokenBacked = false;
return myBackedToken;
}
else
{
return getNewToken();
}
}
/**
* Zur?cklegen eines Tokens.
* * Es kann max. 1 Token zur?ckgelegt werden.
* @param pToken ein Token, das zur?ckgelegt werden soll
*/
public void ungetToken(Object pToken)
{
if (myTokenBacked)
{
MLogger.err("Error (Scanner.ungetToken): Can't \"unget\" more than 1 tokens.");
// => Exception
}
myTokenBacked = true;
myBackedToken = pToken;
}
//---------------------------------------------------------------------------
/**
* Arbeit mit dem Scanner beenden (close).
*/
public void done()
{
if (myReader != null)
{
try
{
myReader.close();
}
catch (IOException e)
{
}
myReader = null;
}
}
@Override
public void close()
{
done();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy