package com.iwco.equipment.gsmmodem;
import gnu.io.CommPortIdentifier;
import gnu.io.NoSuchPortException;
import gnu.io.PortInUseException;
import gnu.io.SerialPort;
import gnu.io.SerialPortEvent;
import gnu.io.SerialPortEventListener;
import gnu.io.UnsupportedCommOperationException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Observable;
import java.util.TooManyListenersException;
/**
* 串口数据读取类,用于windows的串口数据读取
*
*
* @author Macro Lu
* @version 2007-4-4
*/
public class SerialReader extends Observable implements Runnable,
SerialPortEventListener {
static CommPortIdentifier portId;
int delayRead = 200;
public static String phoneContent = "机房监控";
int numBytes; // buffer中的实际数据字节数
private static byte[] readBuffer = new byte[4096]; // 4k的buffer空间,缓存串口读入的数据
static Enumeration portList;
InputStream inputStream;
OutputStream out;
SerialPort serialPort;
HashMap serialParams;
// 端口读入数据事件触发后,等待n毫秒后再读取,以便让数据一次性读完
public static final String PARAMS_DELAY = "delay read"; // 延时等待端口数据准备的时间
public static final String PARAMS_TIMEOUT = "timeout"; // 超时时间
public static final String PARAMS_PORT = "port name"; // 端口名称
public static final String PARAMS_DATABITS = "data bits"; // 数据位
public static final String PARAMS_STOPBITS = "stop bits"; // 停止位
public static final String PARAMS_PARITY = "parity"; // 奇偶校验
public static final String PARAMS_RATE = "rate"; // 波特率
/**
* 初始化端口操作的参数.
* @see
*/
public SerialReader() {
HashMap<String, Comparable> params = new HashMap<String, Comparable>();
params.put(SerialReader.PARAMS_TIMEOUT, 1000); // 设备超时时间 1秒
params.put(SerialReader.PARAMS_DELAY, 200); // 端口数据准备时间 1秒
params.put(SerialReader.PARAMS_DATABITS, SerialPort.DATABITS_8); // 数据位
params.put(SerialReader.PARAMS_STOPBITS, SerialPort.STOPBITS_1); // 停止位
params.put(SerialReader.PARAMS_PARITY, SerialPort.PARITY_NONE); // 无奇偶校验
serialParams = params;
}
public boolean openPort(String ports, int baudrate, String phoneContent) {
boolean rsBool = false;
try {
// 参数初始化
final int timeout = Integer.parseInt(serialParams.get(PARAMS_TIMEOUT).toString());
final int rate = baudrate;
final int dataBits = Integer.parseInt(serialParams.get(PARAMS_DATABITS).toString());
final int stopBits = Integer.parseInt(serialParams.get(PARAMS_STOPBITS).toString());
final int parity = Integer.parseInt(serialParams.get(PARAMS_PARITY).toString());
delayRead = Integer.parseInt(serialParams.get(PARAMS_DELAY).toString());
final String port = ports;
// 打开端口
portId = CommPortIdentifier.getPortIdentifier(port);
serialPort = (SerialPort) portId.open("SerialReader", timeout);
inputStream = serialPort.getInputStream();
out = serialPort.getOutputStream();
serialPort.addEventListener(this);
serialPort.notifyOnDataAvailable(true);
serialPort.setSerialPortParams(rate, dataBits, stopBits, parity);
rsBool = true;
} catch (final PortInUseException e) {
System.out.println("端口已经被占用!");
e.printStackTrace();
} catch (final TooManyListenersException e) {
System.out.println("端口监听者过多!");
e.printStackTrace();
} catch (final UnsupportedCommOperationException e) {
System.out.println("端口操作命令不支持!");
e.printStackTrace();
} catch (final NoSuchPortException e) {
System.out.println("端口不存在!");
e.printStackTrace();
} catch (final IOException e) {
e.printStackTrace();
}
Thread readThread = new Thread(this);
readThread.start();
return rsBool;
}
/**
* Method declaration
*
*
* @see
*/
public void run() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
}
}
/**
* @describe: 向串口写数据 char[] bytes
* @date:2009-11-5
*/
public void writePort(char[] bytes) throws IOException {
int length= bytes.length;
byte[] sendCmd = new byte[100];
for (int i = 0; i < length; i++){
sendCmd[i] = (byte) bytes[i];
}
out.write(sendCmd, 0, length);
}
/**
* @describe: 向串口写数据 char[] bytes
* @date:2009-11-5
*/
public void writePort(String bytes) throws IOException {
int length = bytes.length(); //取得字符串的长度
byte[] sendCmd = new byte[10000]; //创建一个byte数组
for(int i=0;i<length;i++){
sendCmd[i] = (byte) bytes.indexOf(i);
}
out.write(sendCmd, 0, length);
}
/**
* @describe: 向串口写数据 char bytes
* @date:2009-11-5
*/
public void writePort(char b) throws IOException {
if (out != null) {
out.write(b);
out.flush();
} else {
}
}
/**
* @describe: 读取串口数据
* @date:2009-11-5
*/
public char[] readPackData() throws Exception {
byte[] readBuffer = new byte[1024];
char[] msgPack = null;
int numBytes = 0;
while (inputStream.available() > 0) {
numBytes = inputStream.read(readBuffer);
msgPack = null;
msgPack = new char[numBytes];
for (int i = 0; i < numBytes; i++) {
msgPack[i] = (char) (readBuffer[i] & 0xFF);
}
}
return msgPack;
}
/**
* Method declaration
*
*
* @param event
*
* @see
*/
public void serialEvent(SerialPortEvent event) {
try {
// 等待1秒钟让串口把数据全部接收后在处理
Thread.sleep(delayRead);
} catch (InterruptedException e) {
e.printStackTrace();
}
switch (event.getEventType()) {
case SerialPortEvent.BI: // 10
case SerialPortEvent.OE: // 7
case SerialPortEvent.FE: // 9
case SerialPortEvent.PE: // 8
case SerialPortEvent.CD: // 6
case SerialPortEvent.CTS: // 3
case SerialPortEvent.DSR: // 4
case SerialPortEvent.RI: // 5
case SerialPortEvent.OUTPUT_BUFFER_EMPTY: // 2
break;
case SerialPortEvent.DATA_AVAILABLE: // 1
try {
byte[] readBuffer = new byte[500];
char[] msgPack = null;
int numBytes = 0;
while (inputStream.available() > 0) {
numBytes = inputStream.read(readBuffer);
msgPack = null;
msgPack = new char[numBytes];
for (int i = 0; i < numBytes; i++) {
msgPack[i] = (char) (readBuffer[i] & 0xFF);
}
}
System.out.println("---" + new String(readBuffer));
} catch (IOException e) {
e.printStackTrace();
}
break;
}
}
/**
* @describe: 列举全部串口名称
* @date:2009-11-22
*/
public static List<String> getAllComPorts() {
List<String> comList = new ArrayList<String>();
Enumeration en = CommPortIdentifier.getPortIdentifiers();
CommPortIdentifier portIdRs = null;
while (en.hasMoreElements()) {
portIdRs = (CommPortIdentifier) en.nextElement();
if (portIdRs.getPortType() == CommPortIdentifier.PORT_SERIAL) {
comList.add(portIdRs.getName());
}
}
return comList;
}
/**
* @describe: 关闭串口,释放资源
* @date:2009-11-5
*/
public void close() {
if (out != null) {
try {
inputStream.close();
inputStream = null;
} catch (IOException e) {
}
}
if (serialPort != null) {
serialPort.close();
serialPort = null;
}
}
}
package com.iwco.equipment.gsmmodem;
import java.util.List;
public class Send {
public static void sendSms(List<String> phoneList,String smsContent,SmsSendJob smsSendJob){
smsSendJob.sendMessage(phoneList, smsContent);
smsSendJob.stopService();
}
}
package com.iwco.equipment.gsmmodem;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import com.iwco.dao.IPhone;
import com.iwco.dao.impl.PhoneImpl;
import com.iwco.pojo.Phone;
import com.iwco.pojo.SmsPolicy;
public class SmsSend {
private static IPhone phoneImpl = new PhoneImpl();
private static SmsSendJob smsSendJob;
private static SmsSend smsSend = null;
private SmsSend(String port){
smsSendJob = SmsSendJob.getInstance();
smsSendJob.startService(port, 9600, "SMS");
}
public static SmsSend instance(){
if (smsSend == null) {
smsSend = new SmsSend("COM5");
}
return smsSend;
}
public void send(String content){
//得到搜索条件(查询今天发送的用户)
SmsPolicy smsPolicy = search();
//获得手机列表
List<Phone> phones = phoneImpl.quePhoneByFlag(smsPolicy);
if(phones.size() != 0){
//判断是否满足发送条件,删除不满足条件的用户
List<Phone> phoneSet = check(phones);
List<String> phoneList = new ArrayList<String>();
//遍历发送的详情
Iterator<Phone> iter = phoneSet.iterator();
while(iter.hasNext()){
System.out.println("发送:'" + content + "'给'" + iter.next().getPhoneNumber() + "'");
phoneList.add(iter.next().getPhoneNumber());
}
smsSendJob.sendMessage(phoneList, content);
}
}
//得到搜索条件(查询今天发送的用户)
public static SmsPolicy search(){
SmsPolicy smsPolicy = new SmsPolicy();
smsPolicy.setMonday(1);smsPolicy.setTuesday(1);
smsPolicy.setWednesday(1);smsPolicy.setThursday(1);
smsPolicy.setFriday(1);smsPolicy.setWednesday(1);
smsPolicy.setSunday(1);
Calendar c = Calendar.getInstance();
c.setTime(new Date(System.currentTimeMillis()));
int dayOfWeek = c.get(Calendar.DAY_OF_WEEK);
switch (dayOfWeek) {
case 1:
smsPolicy.setSunday(0);
break;
case 2:
smsPolicy.setMonday(0);
break;
case 3:
smsPolicy.setTuesday(0);
break;
case 4:
smsPolicy.setWednesday(0);
break;
case 5:
smsPolicy.setThursday(0);
break;
case 6:
smsPolicy.setFriday(0);
break;
case 7:
smsPolicy.setSaturday(0);
break;
}
return smsPolicy;
}
//检查是否还在上班时间内
public static boolean checkTime(String startWorking, String endWorking){
try {
//格式化时间
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm");
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
//得到当前时间
Date date = new Date();
//上班时间
String startWork = df.format(date) + " " + startWorking;
Date startDate = format.parse(startWork);
//下班时间
String endWork = df.format(date) + " " + endWorking;
Date endDate = format.parse(endWork);
//返还
return date.after(startDate) && date.before(endDate);
} catch (ParseException e) {
e.printStackTrace();
}
return false;
}
//判断是否满足发送条件
public static List<Phone> check(List<Phone> phones){
//发送列表
List<Phone> phoneSet = new ArrayList<Phone>();
for (int i = 0; i < phones.size(); i++) {
Phone phone = phones.get(i);
//是否只在上班时间发送短信
if (phone.getSmsPolicy().getWorkTime() == 0) {
//判断是否是上班时间
if (checkTime(phone.getSmsPolicy().getStartWork(), phone.getSmsPolicy().getEndWork())) {
phoneSet.add(phone);
}
} else {
phoneSet.add(phone);
}
}
//返还发送列表
return phoneSet;
}
}
package com.iwco.equipment.gsmmodem;
import java.io.IOException;
import java.util.List;
public class SmsSendJob {
private static SmsSendJob smsSendJob = null;
private SmsSendJob(){};
private SerialReader serial = new SerialReader();
private String message;
/**
* @describe: 获取SmsSendJob类单例
* @date:2011-6-24
*/
public static SmsSendJob getInstance() {
if (smsSendJob == null) {
smsSendJob = new SmsSendJob();
return smsSendJob;
}
return smsSendJob;
}
/**
* @describe: 测试短信模块(串口号自动检测,不需要设置)
* @param baudrate: 串口号
* @param baudrate: 波特率
* @param passPort: 程序名
* @return: true:连接成功,并进入运行状态已经初始化 false:失败
* @date:2011-6-24
*/
public boolean startService(String port,int baudrate, String passPort){
boolean val = serial.openPort(port, 9600, passPort);
if (val) {
try {
//at测试
message = "at\r";
serial.writePort(message);
Thread.sleep(500);
//信号质量
message = "AT+CSQ\r+CSQ: 27,99\r";
serial.writePort(message);
Thread.sleep(500);
//报告移动设备的错误
message = "AT+CMEE=0\r";
serial.writePort(message);
Thread.sleep(500);
//选择消息服务
message = "AT+CSMS=0\r+CSMS: 1,1,1\r";
serial.writePort(message);
Thread.sleep(500);
//优先信息格式
message = "AT+CMGF=0\r";
serial.writePort(message);
Thread.sleep(500);
//呼叫线确认陈述
message = "at+clip=1\r";
serial.writePort(message);
Thread.sleep(500);
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return val;
}
/**
* @describe: 给指定的一组手机号码,发送短信
* @param phoneList 手机号码列表
* @param msg 信息内容
* @date:2011-6-24
* String len = SmsService.toSmsLen("13418167027","请注意,机房温湿度温度高于上限,请及时处理。当前温度:40.0%");
*/
public void sendMessage(List<String> phoneList, String msg){
if ( (phoneList != null) && (phoneList.size() > 0) ){
try {
for (int i = 0; i < phoneList.size(); i++) {
//得到信息长度
String len = SmsService.toSmsLen(phoneList.get(i),msg);
message = "at+cmgs="+len+"\r";
serial.writePort(message);
Thread.sleep(500);
//发送短信内容
message = SmsService.toSmsContext(phoneList.get(i),msg);
serial.writePort(message);
Thread.sleep(10000);
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
/**
* 停止服务
*/
public void stopService(){
serial.close();
}
// public static void main(String[] args) throws Exception {
// SerialReader serial = new SerialReader();
boolean val = serial.openPort("COM1", 9600, "SMS");
// if (val) {
// //at测试
// String message = "at\r";
// serial.writePort(message);
// Thread.sleep(500);
// //信号质量
// message = "AT+CSQ\r+CSQ: 27,99\r";
// serial.writePort(message);
// Thread.sleep(500);
// //报告移动设备的错误
// message = "AT+CMEE=0\r";
// serial.writePort(message);
// Thread.sleep(500);
// //选择消息服务
// message = "AT+CSMS=0\r+CSMS: 1,1,1\r";
// serial.writePort(message);
// Thread.sleep(500);
// //优先信息格式
// message = "AT+CMGF=0\r";
// serial.writePort(message);
// Thread.sleep(500);
// //呼叫线确认陈述
// message = "at+clip=1\r";
// serial.writePort(message);
// Thread.sleep(500);
// //得到信息长度
// String len = SmsService.toSmsLen("13418167027","1号温湿度,温度高于上限,温度:24.0");
// message = "at+cmgs="+len+"\r";
// serial.writePort(message);
// Thread.sleep(500);
// //发送短信内容
// message = SmsService.toSmsContext("13418167027","1号温湿度,温度高于上限,温度:24.0");
// serial.writePort(message);
// Thread.sleep(5000);
// //关闭端口
// serial.close();
// }
// }
}
package com.iwco.equipment.gsmmodem;
public class SmsService {
public static String toSmsContext(String phone,String messages){
//设置中心号码
String addr = "00";
// String addr = "0891683108200005F0";
//手机号码
String number = "86" + phone; //因为在中国所以可以固定为86
//手机号码长度是否为偶数,如果不是,最后添加F
if (number.length() % 2 != 0) {
number = number + "F";
}
//手机号码奇数位和偶数位交换
number = change(number);
//短信内容
String msg = message(messages);
//PDU
String start = "11000D91";
String end = "000800";
number = start + number + end + msg;
//短信的内容
String message = addr + number + (char)Integer.parseInt("1A",16);
return message;
}
//得到长度
public static String toSmsLen(String phone,String messages){
//手机号码
String number = "86" + phone;
//手机号码长度是否为偶数,如果不是,最后添加F
if (number.length() % 2 != 0) {
number = number + "F";
}
//手机号码奇数位和偶数位交换
number = change(number);
//短信内容
String msg = message(messages);
//PDU
String start = "11000D91";
String end = "000800";
number = start + number + end + msg;
//短信的发送长度
String len = Integer.toString(number.length() / 2);
return len;
}
public static String message(String message){
String msg = CharacterSetToolkit.toUnicode(message, false);
String len = Integer.toHexString(msg.length() / 2);
if (len.length() == 1) {
len = "0" + len;
}
return len + msg;
}
public static String change(String str){
StringBuffer sb = new StringBuffer();
String[] value = new String[str.length()];
String[] s = str.split("");
//拆分
for (int i = 0; i < value.length; i++) {
value[i] = s[i+1];
}
//位置交换
for (int i = 0; i < value.length;) {
String temp = value[i];
value[i] = value[i+1];
value[i+1] = temp;
i = i+2;
}
//toString
for (int i = 0; i < value.length; i++) {
sb.append(value[i]);
}
return sb.toString();
}
}
package com.iwco.equipment.gsmmodem;
/***
*进行字符操作的工具类。
*/
public class CharacterSetToolkit{
/***//**CreatesanewinstanceofCharacterSetToolkit*/
public CharacterSetToolkit(){
}
private static final char[] hexDigit = {
'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'
};
private static char toHex(int nibble){
return hexDigit[(nibble&0xF)];
}
/**
* 将字符串编码成 Unicode 。
* @param theString 待转换成Unicode编码的字符串。
* @param escapeSpace 是否忽略空格。
* @return 返回转换后Unicode编码的字符串。
*/
public static String toUnicode(String theString, boolean escapeSpace) {
int len = theString.length();
int bufLen = len * 2;
if (bufLen < 0) {
bufLen = Integer.MAX_VALUE;
}
StringBuffer outBuffer = new StringBuffer(bufLen);
for(int x=0; x<len; x++) {
char aChar = theString.charAt(x);
// Handle common case first, selecting largest block that
// avoids the specials below
if ((aChar > 61) && (aChar < 127)) {
if (aChar == '\\') {
outBuffer.append('\\'); outBuffer.append('\\');
continue;
}
outBuffer.append(aChar);
continue;
}
switch(aChar) {
case ' ':
if (x == 0 || escapeSpace)
outBuffer.append('\\');
outBuffer.append(' ');
break;
case '\t':outBuffer.append('\\'); outBuffer.append('t');
break;
case '\n':outBuffer.append('\\'); outBuffer.append('n');
break;
case '\r':outBuffer.append('\\'); outBuffer.append('r');
break;
case '\f':outBuffer.append('\\'); outBuffer.append('f');
break;
case '=': // Fall through
case ':': // Fall through
case '#': // Fall through
case '!':
outBuffer.append('\\'); outBuffer.append(aChar);
break;
case '.':
outBuffer.append(toHex((aChar >> 12) & 0xF));
outBuffer.append(toHex((aChar >> 8) & 0xF));
outBuffer.append(toHex((aChar >> 4) & 0xF));
outBuffer.append(toHex( aChar & 0xF));
break;
case '%':
outBuffer.append(toHex((aChar >> 12) & 0xF));
outBuffer.append(toHex((aChar >> 8) & 0xF));
outBuffer.append(toHex((aChar >> 4) & 0xF));
outBuffer.append(toHex( aChar & 0xF));
break;
case '0':
outBuffer.append(toHex((aChar >> 12) & 0xF));
outBuffer.append(toHex((aChar >> 8) & 0xF));
outBuffer.append(toHex((aChar >> 4) & 0xF));
outBuffer.append(toHex( aChar & 0xF));
break;
case '1':
outBuffer.append(toHex((aChar >> 12) & 0xF));
outBuffer.append(toHex((aChar >> 8) & 0xF));
outBuffer.append(toHex((aChar >> 4) & 0xF));
outBuffer.append(toHex( aChar & 0xF));
break;
case '2':
outBuffer.append(toHex((aChar >> 12) & 0xF));
outBuffer.append(toHex((aChar >> 8) & 0xF));
outBuffer.append(toHex((aChar >> 4) & 0xF));
outBuffer.append(toHex( aChar & 0xF));
break;
case '3':
outBuffer.append(toHex((aChar >> 12) & 0xF));
outBuffer.append(toHex((aChar >> 8) & 0xF));
outBuffer.append(toHex((aChar >> 4) & 0xF));
outBuffer.append(toHex( aChar & 0xF));
break;
case '4':
outBuffer.append(toHex((aChar >> 12) & 0xF));
outBuffer.append(toHex((aChar >> 8) & 0xF));
outBuffer.append(toHex((aChar >> 4) & 0xF));
outBuffer.append(toHex( aChar & 0xF));
break;
case '5':
outBuffer.append(toHex((aChar >> 12) & 0xF));
outBuffer.append(toHex((aChar >> 8) & 0xF));
outBuffer.append(toHex((aChar >> 4) & 0xF));
outBuffer.append(toHex( aChar & 0xF));
break;
case '6':
outBuffer.append(toHex((aChar >> 12) & 0xF));
outBuffer.append(toHex((aChar >> 8) & 0xF));
outBuffer.append(toHex((aChar >> 4) & 0xF));
outBuffer.append(toHex( aChar & 0xF));
break;
case '7':
outBuffer.append(toHex((aChar >> 12) & 0xF));
outBuffer.append(toHex((aChar >> 8) & 0xF));
outBuffer.append(toHex((aChar >> 4) & 0xF));
outBuffer.append(toHex( aChar & 0xF));
break;
case '8':
outBuffer.append(toHex((aChar >> 12) & 0xF));
outBuffer.append(toHex((aChar >> 8) & 0xF));
outBuffer.append(toHex((aChar >> 4) & 0xF));
outBuffer.append(toHex( aChar & 0xF));
break;
case '9':
outBuffer.append(toHex((aChar >> 12) & 0xF));
outBuffer.append(toHex((aChar >> 8) & 0xF));
outBuffer.append(toHex((aChar >> 4) & 0xF));
outBuffer.append(toHex( aChar & 0xF));
break;
default:
if ((aChar < 0x0020) || (aChar > 0x007e)) {
outBuffer.append(toHex((aChar >> 12) & 0xF));
outBuffer.append(toHex((aChar >> 8) & 0xF));
outBuffer.append(toHex((aChar >> 4) & 0xF));
outBuffer.append(toHex( aChar & 0xF));
} else {
outBuffer.append(aChar);
}
}
}
return outBuffer.toString();
}
/**
* 从 Unicode 码转换成编码前的特殊字符串。
* @param in Unicode编码的字符数组。
* @param off 转换的起始偏移量。
* @param len 转换的字符长度。
* @param convtBuf 转换的缓存字符数组。
* @return 完成转换,返回编码前的特殊字符串。
*/
public String fromUnicode(char[] in, int off, int len, char[] convtBuf) {
if (convtBuf.length < len) {
int newLen = len * 2;
if (newLen < 0) {
newLen = Integer.MAX_VALUE;
}
convtBuf = new char[newLen];
}
char aChar;
char[] out = convtBuf;
int outLen = 0;
int end = off + len;
while (off < end) {
aChar = in[off++];
if (aChar == '\\') {
aChar = in[off++];
if (aChar == 'u') {
// Read the xxxx
int value = 0;
for (int i = 0; i < 4; i++) {
aChar = in[off++];
switch (aChar) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
value = (value << 4) + aChar - '0';
break;
case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
value = (value << 4) + 10 + aChar - 'a';
break;
case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
value = (value << 4) + 10 + aChar - 'A';
break;
default:
throw new IllegalArgumentException(
"Malformed \\uxxxx encoding.");
}
}
out[outLen++] = (char) value;
} else {
if (aChar == 't') {
aChar = '\t';
} else if (aChar == 'r') {
aChar = '\r';
} else if (aChar == 'n') {
aChar = '\n';
} else if (aChar == 'f') {
aChar = '\f';
}
out[outLen++] = aChar;
}
} else {
out[outLen++] = (char) aChar;
}
}
return new String(out, 0, outLen);
}
}