How can I optimize the processing of strings?
Your problem is you are making n copies of t and concatenating them. This is a simple approach, but quite expensive - it turns what could be an O(n) solution into an O(n2) one.
Instead, just check each char of s:
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) != t.charAt(i % t.length())) {
return -1:
}
}
Do not make new strings, but use String.regionMatches.
Use String.length and modulo % == 0.
The smallest substring of t can be done using the same method.
Coding:
new String(string) ist never needed.
String += is slow. Better use StringBuilder.
No code to not spoil your coding.
Just a remark:
in general working with char[] is much faster than working with String.
(but nowhere near as convenient)
And make your variables final when they are final.
(it makes no difference to performance, but aids understanding)
Anyway, this might do it:
import java.util.Arrays;
class Result {
public static int findSmallestDivisor(final String s, final String t) {
final int lenS = s.length();
final int lenT = t.length();
/*
* Get Length & Chars of shortest & longest Strings...
*/
final int lenShort;
final int lenLong;
final char[] charsShort;
final char[] charsLong;
if (lenS < lenT) {
lenShort = lenS; charsShort = s.toCharArray();
lenLong = lenT; charsLong = t.toCharArray();
} else {
lenShort = lenT; charsShort = t.toCharArray();
lenLong = lenS; charsLong = s.toCharArray();
}
/*
* Get the Factor & exit if there's a remainder...
*/
final int factor = lenLong / lenShort;
final int factorRem = lenLong % lenShort;
if (factorRem != 0) {
return -1;
}
/*
* Try all possible divisors...
*/
for (int d=1; d <= lenShort; d++) {
final int n = lenShort / d;
final int nRem = lenShort % d;
if (nRem != 0) {
continue;
}
final char[] dChars = Arrays.copyOf(charsShort, d);
final char[] dCharsMultipliedShort = multiplyChars(dChars, n);
final char[] dCharsMultipliedLong = multiplyChars(dCharsMultipliedShort, factor);
if (Arrays.equals(charsShort, dCharsMultipliedShort)
&& Arrays.equals(charsLong, dCharsMultipliedLong )) {
return d;
}
}
return -1;
}
private static char[] multiplyChars(final char[] a, final int n) {
// if (n == 0) { // Necessary: otherwise ArrayIndexOutOfBoundsException in getChars(...)
// return new char[] {}; // (n is never 0)
// }
if (n == 1) { // Optional: optimisation
return a;
}
final int aLength = a.length;
final char[] charsMultiplied = new char[aLength * n];
System.arraycopy(a, 0, charsMultiplied, 0, aLength); // Fill in 1st occurrence
/*
* Copy 1st occurrence to the remaining occurrences...
*/
for (int i = 1; i < n; i++) {
System.arraycopy(charsMultiplied, 0, charsMultiplied, i*aLength, aLength);
}
return charsMultiplied;
}
}
This post is a carryover from a previous Using .properties Resource File ResourceBundle in an XPage. All Kudos goes to Sean Cullm, Matt White,
Julian Robichaus in this post Creating an Xpage resource file via DXL without a temporary file using LotusScript.
I ran into the error: **Base64 byte stream contains invalid data or is too large to store in a single note item** with some of the key:value pairs being realllly big. To get around the problem of having strings chopped or the error above thrown, I shifted over a JAVA solution to solve what seems to be a LotusScript problem.
Java Solution:
JavaAgent extends AgentBase:
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Vector;
import lotus.domino.AgentBase;
import lotus.domino.AgentContext;
import lotus.domino.Database;
import lotus.domino.DateTime;
import lotus.domino.DxlImporter;
import lotus.domino.Log;
import lotus.domino.NotesException;
import lotus.domino.Session;
import lotus.domino.Stream;
import lotus.domino.View;
import lotus.domino.ViewEntry;
import lotus.domino.ViewEntryCollection;
public class JavaAgent extends AgentBase {
public Database db;
public View view;
static DxlImporter importer = null;
Log log;
DateTime dt;
public void NotesMain() {
try {
Session session = getSession();
AgentContext agentContext = session.getAgentContext();
// Document contextDoc = agentContext.getDocumentContext();
log = session.createLog("Agent Log");
log.openAgentLog();
this.db = agentContext.getCurrentDatabase();
this.view = db.getView("dojoprivotdatadocs");
importer = session.createDxlImporter();
importer.setReplaceDbProperties(true);
importer.setReplicaRequiredForReplaceOrUpdate(false);
importer.setAclImportOption(DxlImporter.DXLIMPORTOPTION_IGNORE);
importer
.setDesignImportOption(DxlImporter.DXLIMPORTOPTION_REPLACE_ELSE_CREATE);
importer
.setDocumentImportOption(DxlImporter.DXLIMPORTOPTION_IGNORE);
// importer.importDxl(generateDXL("", "", db.getReplicaID()), db);
importer.importDxl(generateDXL("", "", ""), db);
view.setAutoUpdate(true);
view.recycle();
db.recycle();
} catch (Exception e) {
e.printStackTrace();
System.out.println("end__" + e.getMessage());
} finally {
try {
System.out.println(importer.getLog());
} catch (Exception e) {
e.printStackTrace();
System.out.println("final: " + e.getMessage());
}
}
}
public Stream generateDXL(String data, final String libName,
final String dbReplicaId) throws NotesException {
Session session = getSession();
Stream dxlStream = session.createStream();
//NOTE: I left the raw DXL generated by an NotesNoteCollection export
//the import DXL is not verbose like the exported DXL, the DXL exported is commented out
try {
this.view.refresh();
this.view.setAutoUpdate(false);
dxlStream.writeText("<?xml version='1.0' encoding='utf-8'?>");
dxlStream
.writeText("<!DOCTYPE database SYSTEM 'xmlschemas/domino_9_0_1.dtd'>");
/**
* dxl .append("<database xmlns='http://www.lotus.com/dxl' version='9.0' maintenanceversion='1.0' replicaid='"
* + dbReplicaId +"' path='CN=dom001/OU=SERVER/O=PC!!SSH\\ESA\\PolarColFileData.nsf' title='Polar Col File Data'>"
* );
**/
dxlStream
.writeText("<database xmlns='http://www.lotus.com/dxl' replicaid='882580D6006A6F64'>");
/**
* dxl .append("<fileresource name='base64.properties' noreplace='false' publicaccess='false' designerversion='9.0.1'>"
* );
**/
dxlStream
.writeText("<fileresource name='dojoPivotData.properties' noreplace='false' publicaccess='false' charset='ISO-8859-1'>");
// dxlStream
// .writeText("<created><datetime dst='true'>20171214T101814,59-07</datetime></created>");
dxlStream.writeText("<filedata>");
// Base64 base64 = new Base64();
dxlStream.writeText(Base64.encode(getViewEntires().readText()));
dxlStream.writeText("</filedata></fileresource></database>");
} catch (NotesException ne) {
ne.printStackTrace();
System.out.println("generateDXL:: " + ne.getMessage());
} catch (Exception e) {
e.printStackTrace();
System.out.println("generateDXL:: " + e.getMessage());
}
return dxlStream;
}
public Stream getViewEntires() throws NotesException {
Stream base64Stream = getSession().createStream();
String eString = "";
try {
ViewEntryCollection vec = this.view.getAllEntries();
ViewEntry tmpentry;
ViewEntry entry = vec.getFirstEntry();
while (entry != null) {
Vector colvals = entry.getColumnValues();
base64Stream
.writeText(colvals.get(0).toString(), Stream.EOL_CR);
tmpentry = vec.getNextEntry();
entry.recycle();
entry = tmpentry;
}
dt = getSession().createDateTime("Today");
dt.setNow();
base64Stream.writeText("#generated=" + dt.getDateOnly() + " "
+ dt.getTimeOnly() + " TZ:" + dt.getTimeZone(),
Stream.EOL_CR);
dt.recycle();
base64Stream.setPosition(0);
} catch (NotesException ne) {
ne.printStackTrace();
System.out.println("getViewEntires:: " + eString + ": "
+ ne.getMessage());
} catch (Exception e) {
e.printStackTrace();
System.out.println("getViewEntires:: " + eString + ": "
+ e.getMessage());
}
return base64Stream;
}
/**
* converts a integer to a byte array in little endian order
*
* #param i
* integer to convert
* #return byte array
*/
static byte[] toBytes(final int i) {
ByteBuffer b = ByteBuffer.allocate(4);
b.order(ByteOrder.LITTLE_ENDIAN);
b.putInt(i);
return b.array();
}
}
Ascii.java
/*
* Copyright IBM Corp. 2012-2013
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
/**
* Ascii constants.
* <p>
* Some useful constants.
* </p>
*
* #ibm-not-published
*/
public interface Ascii {
public static final byte CASE_OFFSET = 32;
public static final byte A = 65;
public static final byte B = 66;
public static final byte C = 67;
public static final byte D = 68;
public static final byte E = 69;
public static final byte F = 70;
public static final byte G = 71;
public static final byte H = 72;
public static final byte I = 73;
public static final byte J = 74;
public static final byte K = 75;
public static final byte L = 76;
public static final byte M = 77;
public static final byte N = 78;
public static final byte O = 79;
public static final byte P = 80;
public static final byte Q = 81;
public static final byte R = 82;
public static final byte S = 83;
public static final byte T = 84;
public static final byte U = 85;
public static final byte V = 86;
public static final byte W = 87;
public static final byte X = 88;
public static final byte Y = 89;
public static final byte Z = 90;
public static final byte a = 97;
public static final byte b = 98;
public static final byte c = 99;
public static final byte d = 100;
public static final byte e = 101;
public static final byte f = 102;
public static final byte g = 103;
public static final byte h = 104;
public static final byte i = 105;
public static final byte j = 106;
public static final byte k = 107;
public static final byte l = 108;
public static final byte m = 109;
public static final byte n = 110;
public static final byte o = 111;
public static final byte p = 112;
public static final byte q = 113;
public static final byte r = 114;
public static final byte s = 115;
public static final byte t = 116;
public static final byte u = 117;
public static final byte v = 118;
public static final byte w = 119;
public static final byte x = 120;
public static final byte y = 121;
public static final byte z = 122;
public static final byte ZERO = 48;
public static final byte ONE = 49;
public static final byte TWO = 50;
public static final byte THREE = 51;
public static final byte FOUR = 52;
public static final byte FIVE = 53;
public static final byte SIX = 54;
public static final byte SEVEN = 55;
public static final byte EIGHT = 56;
public static final byte NINE = 57;
public static final byte TAB = 9;
public static final byte LF = 10;
public static final byte FF = 12;
public static final byte CR = 13;
public static final byte SPACE = 32;
public static final byte PERIOD = 46;
public static final byte SLASH = 47;
public static final byte BACK_SLASH = 92;
public static final byte COLON = 58;
public static final byte SEMICOLON = 59;
public static final byte EQUALS = 61;
public static final byte QUOTE = 34;
public static final byte LT = 60;
public static final byte GT = 62;
public static final byte OP = 40;
public static final byte CP = 41;
public static final byte AT = 64;
public static final byte UNDERSCORE = 95;
public static final byte STAR = 42;
public static final byte PERCENT = 37;
public static final byte HYPHEN = 45;
public static final byte PLUS = 43;
public static final byte OPEN_CURLY = 123;
public static final byte CLOSE_CURLY = 125;
public static final byte OPEN_ANGLE = 60;
public static final byte CLOSE_ANGLE = 62;
/** The CR/LF pair. */
public static final byte[] CRLF = { CR, LF };
}
Base64OutputStream.java
/*
* Copyright IBM Corp. 2012-2013
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
* A Base64 content transfer encoding filter stream.
* <p>
* From RFC 2045, section 6.8:
* <p>
* The Base64 Content-Transfer-Encoding is designed to represent arbitrary
* sequences of octets in a form that need not be humanly readable. The encoding
* and decoding algorithms are simple, but the encoded data are consistently
* only about 33 percent larger than the unencoded data.
*
* #ibm-api
*/
public class Base64OutputStream extends FilterOutputStream {
private final byte[] _buffer;
private int _buflen;
private int _count;
private final int _lineLength;
/**
* Default constructor.
*
* #param out
* the underlying output stream to encode
* #pre out != null
* #post out != null
*/
public Base64OutputStream(OutputStream out) {
this(out, Integer.MAX_VALUE);
}
/**
* Constructor.
*
* #param out
* the underlying output stream to encode
* #param lineLength
* the line length
* #pre out != null
* #pre lineLength > 0
* #post out != null
*/
public Base64OutputStream(OutputStream out, int lineLength) {
super(out);
_buflen = 0;
_count = 0;
_buffer = new byte[3];
_lineLength = lineLength;
}
/**
* Writes the specified byte to this output stream.
*
* #param ch
* character to write/encode
* #throws IOException
* IO Exception occurred
* #pre out != null
* #post out != null
*/
public void write(int ch) throws IOException {
_buffer[_buflen++] = (byte) ch;
if (_buflen == 3) {
encode();
_buflen = 0;
}
}
/**
* Writes <code>b.length</code> bytes from the specified byte array to this
* output stream.
*
* #param b
* buffer to write/encode
* #throws IOException
* IO Exception occurred
* #pre out != null
* #post out != null
*/
public void write(byte[] b) throws IOException {
write(b, 0, b.length);
}
/**
* Writes <code>len</code> bytes from the specified byte array starting at
* offset <code>off</code> to this output stream.
*
* #param b
* buffer to write/encode
* #param off
* offset to start of buffer to write/encode
* #param len
* number of bytes from buffer to write/encode
* #throws IOException
* IO Exception occurred
* #pre off < b.length
* #pre off+len < b.length
* #pre out != null
* #post out != null
*/
public void write(byte[] b, int off, int len) throws IOException {
for (int i = 0; i < len; i++) {
write(b[off + i]);
}
}
/**
* Flushes this output stream and forces any buffered output bytes to be
* written out.
*
* #throws IOException
* IO Exception occurred
* #pre out != null
* #post _buflen == 0
*/
public void flush() throws IOException {
if (_buflen > 0) {
encode();
_buflen = 0;
}
out.flush();
}
/**
* Closes this output stream and releases any system resources associated
* with this stream.
*
* #throws IOException
* IO Exception occurred
* #pre out != null
* #post $none
*/
public void close() throws IOException {
flush();
out.close();
}
/**
* Encode current buffer bytes
*
* #throws IOException
* IO Exception occurred
* #pre out != null
*/
private void encode() throws IOException {
if ((_count + 4) > _lineLength) {
out.write(Ascii.CR);
out.write(Ascii.LF);
_count = 0;
}
if (_buflen == 1) {
byte b = _buffer[0];
int i = 0;
out.write(IoConstants.B64_SRC_MAP[b >>> 2 & 0x3f]);
out
.write(IoConstants.B64_SRC_MAP[(b << 4 & 0x30)
+ (i >>> 4 & 0xf)]);
out.write(Ascii.EQUALS);
out.write(Ascii.EQUALS);
} else if (_buflen == 2) {
byte b1 = _buffer[0], b2 = _buffer[1];
int i = 0;
out.write(IoConstants.B64_SRC_MAP[b1 >>> 2 & 0x3f]);
out.write(IoConstants.B64_SRC_MAP[(b1 << 4 & 0x30)
+ (b2 >>> 4 & 0xf)]);
out.write(IoConstants.B64_SRC_MAP[(b2 << 2 & 0x3c)
+ (i >>> 6 & 0x3)]);
out.write(Ascii.EQUALS);
} else {
byte b1 = _buffer[0], b2 = _buffer[1], b3 = _buffer[2];
out.write(IoConstants.B64_SRC_MAP[b1 >>> 2 & 0x3f]);
out.write(IoConstants.B64_SRC_MAP[(b1 << 4 & 0x30)
+ (b2 >>> 4 & 0xf)]);
out.write(IoConstants.B64_SRC_MAP[(b2 << 2 & 0x3c)
+ (b3 >>> 6 & 0x3)]);
out.write(IoConstants.B64_SRC_MAP[b3 & 0x3f]);
}
_count += 4;
}
}
Base64.java
/*
* Copyright IBM Corp. 2012-2013
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
import java.io.IOException;
/**
* Encodes and decodes to and from Base64 notation.
*
* #ibm-api
*/
public class Base64 {
/**
* Decode a base64 string to an ascii string.
*
* #param base64str
* the string to decode
* #return
* #ibm-api
*/
public static String decode(String base64str) {
try {
StringInputStream bais = new StringInputStream(base64str);
Base64.InputStream b64 = new Base64.InputStream(bais);
StringBuffer buf = new StringBuffer();
int byt;
while ((byt = b64.read()) >= 0) {
buf.append((char) byt);
}
return buf.toString();
} catch (IOException ex) {
ex.printStackTrace();
return null;
}
}
/**
* Encode a string to base64.
*
* #param str
* the string to encode
* #return
* #ibm-api
*/
public static String encode(String str) {
try {
StringBuidlerOutputStream baos = new StringBuidlerOutputStream(str
.length() * 3 / 2);
Base64.OutputStream b64 = new Base64.OutputStream(baos);
int len = str.length();
for (int i = 0; i < len; i++) {
int c = (str.charAt(i)) & 0x00FF;
b64.write(c);
}
b64.flushBuffer();
return baos.builder.toString();
} catch (IOException ex) {
ex.printStackTrace();
return null;
}
}
public static class StringInputStream extends java.io.InputStream {
private final String str;
private int ptr;
public StringInputStream(String str) {
this.str = str;
}
public int read() throws IOException {
if (ptr < str.length()) {
return str.charAt(ptr++);
}
return -1;
}
}
public static class StringBufferOutputStream extends java.io.OutputStream {
private final StringBuffer buffer;
public StringBufferOutputStream(int size) {
this.buffer = new StringBuffer(size);
}
public StringBuffer getStringBuffer() {
return buffer;
}
public void write(int b) throws IOException {
buffer.append((char) b);
}
}
public static class StringBuidlerOutputStream extends java.io.OutputStream {
private final StringBuilder builder;
public StringBuidlerOutputStream(int size) {
this.builder = new StringBuilder(size);
}
public StringBuilder getStringBuilder() {
return builder;
}
public void write(int b) throws IOException {
builder.append((char) b);
}
}
public static class OutputStream extends Base64OutputStream {
public OutputStream(java.io.OutputStream out) {
super(out);
}
public void flushBuffer() throws IOException {
flush();
}
}
public static class InputStream extends Base64InputStream {
public InputStream(java.io.InputStream in) {
super(in);
}
}
}
Base64InputStream.java
/*
* Copyright IBM Corp. 2012-2013
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* A Base64 content transfer encoding filter stream.
* <p>
* From RFC 2045, section 6.8:
* <p>
* The Base64 Content-Transfer-Encoding is designed to represent arbitrary
* sequences of octets in a form that need not be humanly readable. The encoding
* and decoding algorithms are simple, but the encoded data are consistently
* only about 33 percent larger than the unencoded data.
*
* #ibm-api
*/
public class Base64InputStream extends FilterInputStream {
private final byte[] _buffer;
private int _buflen;
private int _index;
private final byte[] _decodeBuf;
/**
* Constructs an input stream that decodes an underlying Base64-encoded
* stream.
*
* #param in
* the Base64-encoded stream
* #ibm-api
*/
public Base64InputStream(InputStream in) {
super(in);
_buflen = 0;
_index = 0;
_decodeBuf = new byte[4];
_buffer = new byte[3];
}
/**
* Reads the next byte of data from the input stream.
*
* #throws IOException
* IO Exception occurred
* #return next byte in data stream
*/
public int read() throws IOException {
if (_index >= _buflen) {
decode();
if (_buflen == 0) {
return -1;
}
_index = 0;
}
return _buffer[_index++] & 0xFF;
}
/**
* Reads up to len bytes of data from the input stream into an array of
* bytes.
*
* #param b
* buffer to put data
* #param off
* offset to start of buffer
* #param len
* number of bytes from buffer
* #throws IOException
* IO Exception occurred
* #return number of bytes read
*/
public int read(byte[] b, int off, int len) throws IOException {
try {
int l = 0;
for (; l < len; l++) {
int ch = read();
if (ch == -1) {
if (l == 0) {
return -1;
} else {
break;
}
}
b[off + l] = (byte) ch;
}
return l;
} catch (IOException ioe) {
return -1;
}
}
/**
* Returns the number of bytes that can be read (or skipped over) from this
* input stream without blocking by the next caller of a method for this
* input stream.
*
* #throws IOException
* IO Exception occurred
* #return number of bytes that can be read
*/
public int available() throws IOException {
return (in.available() * 3) / 4 + (_buflen - _index);
}
/**
* Decode Base64 encoded buffer
*
* #throws IOException
* IO Exception occurred
*/
private void decode() throws IOException {
_buflen = 0;
// Loop until we hit EOF or non-line-termination char
int ch = Ascii.LF;
while (ch == Ascii.LF || ch == Ascii.CR) {
ch = in.read();
if (ch == -1) {
return;
}
}
_decodeBuf[0] = (byte) ch;
int j = 3, l;
for (int k = 1; (l = in.read(_decodeBuf, k, j)) != j; k += l) {
if (l == -1) {
throw new IOException("Base64 encoding error"); // $NLS-Base64InputStream.Base64encodingerror-1$
}
j -= l;
}
byte b0 = IoConstants.B64_DST_MAP[_decodeBuf[0] & 0xFF];
byte b2 = IoConstants.B64_DST_MAP[_decodeBuf[1] & 0xFF];
_buffer[_buflen++] = (byte) (b0 << 2 & 0xfc | b2 >>> 4 & 0x3);
if (_decodeBuf[2] != Ascii.EQUALS) {
b0 = b2;
b2 = IoConstants.B64_DST_MAP[_decodeBuf[2] & 0xFF];
_buffer[_buflen++] = (byte) (b0 << 4 & 0xf0 | b2 >>> 2 & 0xf);
if (_decodeBuf[3] != Ascii.EQUALS) {
byte b1 = b2;
b2 = IoConstants.B64_DST_MAP[_decodeBuf[3] & 0xFF];
_buffer[_buflen++] = (byte) (b1 << 6 & 0xc0 | b2 & 0x3f);
}
}
}
}
IoConstants.java
/*
* Copyright IBM Corp. 2012-2013
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
/**
* Useful constants for base64 package.
*
* #ibm-not-published
*/
public class IoConstants {
/**
* RFC822 requires that header lines are limited to 998 octets (excluding
* CRLF)
*/
public static final int MAX_RFC822_LINE_LENGTH = 998;
/**
* RFC 2822 requires that body content lines can never be more than 998
* octets (excluding CRLF)
*/
public static final int MAX_RFC2822_LINE_LENGTH = 998;
/**
* Map used for Base64 encoding
*/
public static final char[] B64_SRC_MAP = { 'A', 'B', 'C', 'D', 'E', 'F',
'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5',
'6', '7', '8', '9', '+', '/' };
/**
* Map used for Base64 decoding
*/
public static final byte[] B64_DST_MAP = new byte[256];
/**
* Char array used in decimal to hexidecimal conversion.
*/
public static final char[] HEX_CHARS = { '0', '1', '2', '3', '4', '5', '6',
'7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
/** Construct mapping from source to destination maps */
static {
for (int i = 0; i < B64_DST_MAP.length; i++) {
B64_DST_MAP[i] = -1;
}
for (int i = 0; i < B64_SRC_MAP.length; i++) {
B64_DST_MAP[B64_SRC_MAP[i]] = (byte) i;
}
}
}
I need to write an application that fist converts a string to unicode and then add 2 to the unicode value to create a new string.
Basically, if the input is: password is RhYxtz, then the output should look like: rcuuyqtf ku TjAzvb
the following code is what I have so far:
public static void main(String[] args){
System.out.print ("Enter text: ");
Scanner scan = new Scanner(System.in);
String text = scan.nextLine();
int length = text.length();
for(int i = 0; i < length; i ++){
char currentChar = text.charAt(i);
int currentChar2 = currentChar+2;
String s = String.format ("\\u%04x", currentChar2);
System.out.println ("Encoded message: " + s);
}
}
The problem is that I don't know how to convert the unicode back into a letter string and how to keep the format the same as the input. Could anyone help me? Thanks.
Unicode code points can be gathered in java 8 as:
public static String encryped(String s) {
int[] cps = s.codePoints()
.mapToInt((cp) -> cp + 2)
.toArray();
return new String(cps, 0, cps.length);
}
or in a loop with codePointAt in earlier versions.
Java char (2 bytes) are UTF-16, and their int value is not always a Unicode symbol aka code point.
Try this:
import java.util.Scanner;
public class Example {
public static void main(String[] args) {
System.out.print ("Enter text: ");
Scanner scan = new Scanner(System.in);
String text = scan.nextLine();
int length = text.length();
String s = "";
for(int i = 0; i < length; i ++){
char currentChar = text.charAt(i);
if (currentChar == ' '){
s += currentChar;
} else {
s += (char) (currentChar + 2);
}
}
System.out.println ("Encoded message: " + s);
}
}
This should work for US ASCII letters:
StringBuilder buf = new StringBuilder(length);
for(int i = 0; i < length; i ++){
char currentChar = text.charAt(i);
if (currentChar < 128 && Character.isLetter(currentChar)) {
if (currentChar == 'y' || currentChar == 'z'
|| currentChar == 'Y' || currentChar == 'Z') {
buf.append((char) (currentChar + 2 - 26));
} else {
buf.append((char) (currentChar + 2));
}
} else {
buf.append(currentChar);
}
}
System.out.println(buf.toString());
I have issues understanding how to convert a hex value to a duration.
Here are some examples I've seen in the case I study:
2b3da = 2:44.986
2bf64 = 2:47.868
2c84a = 2:50.074
Could someone help to understand how those results are reached ?
Thanks.
string hex1;
string[] hex = new string[16];
hex[0] = hex1.Substring(0, 2);
hex[1] = hex1.Substring(2, 2);
hex[2] = hex1.Substring(4, 2);
hex[3] = hex1.Substring(6, 2);
hex[4] = hex1.Substring(8, 2);
hex[5] = hex1.Substring(10, 2);
hex[6] = hex1.Substring(12, 2);
hex[7] = hex1.Substring(14, 2);
//WE DONOT NEED TO REVERSE THE STRING
//CONVERTING TO INT SO WE CAN ADD TO THE BYTE[]
int[] decValue = new int[8];
for (int i = 0; i < 8; i++)
{
decValue[i] = Convert.ToInt32(hex[i], 16);
}
//CONVERTING TO BYTE BEFORE WE CAN CONVERT TO UTC
byte[] timeByte = new byte[8];
for (int i = 0; i < 8; i++)
timeByte[i] = (byte)decValue[i];
DateTime convertedTime = ConvertWindowsDate(timeByte);
textBox7.Text = convertedTime.ToString();
}
public static DateTime ConvertWindowsDate(byte[] bytes)
{
if (bytes.Length != 8) throw new ArgumentException();
return DateTime.FromFileTimeUtc(BitConverter.ToInt64(bytes, 0));
}
Input : 0060CE5601D6CE01
Output : 31-10-2013 06:20:48
The String(byte[] bytes) constructor and String.getBytes() method are not implemented by GWT JRE emulation String class.
Does anybody know of an implementation? I do not want to use char[], But it seems like there is no other solution.
If you create large arrays in Chrome, you might run into a Uncaught RangeError: Maximum call stack size exceeded exception. The code from LINEMAN78 can be modified to use a StringBuilder, which avoids this issue.
public static String getString(byte[] bytes, int bytesPerChar)
{
if (bytes == null) throw new IllegalArgumentException("bytes cannot be null");
if (bytesPerChar < 1) throw new IllegalArgumentException("bytesPerChar must be greater than 1");
final int length = bytes.length / bytesPerChar;
final StringBuilder retValue = new StringBuilder();
for (int i = 0; i < length; i++)
{
char thisChar = 0;
for (int j = 0; j < bytesPerChar; j++)
{
int shift = (bytesPerChar - 1 - j) * 8;
thisChar |= (0x000000FF << shift) & (((int) bytes[i * bytesPerChar + j]) << shift);
}
retValue.append(thisChar);
}
return retValue.toString();
}
The following code should work, just specify the number of bytes per character.
public class GwtPlayground implements EntryPoint
{
static final Logger logger = Logger.getLogger("");
#Override
public void onModuleLoad()
{
VerticalPanel loggerArea = new VerticalPanel();
logger.addHandler(new HasWidgetsLogHandler(loggerArea));
RootPanel.get().add(loggerArea);
String original = new String("A" + "\uffea" + "\u00f1" + "\u00fc" + "C");
logger.info("original = " + original);
byte[] utfBytes = getBytes(original, 2);
String roundTrip = getString(utfBytes, 2);
logger.info("roundTrip = " + roundTrip);
}
public static byte[] getBytes(String string, int bytesPerChar)
{
char[] chars = string.toCharArray();
byte[] toReturn = new byte[chars.length * bytesPerChar];
for (int i = 0; i < chars.length; i++)
{
for (int j = 0; j < bytesPerChar; j++)
toReturn[i * bytesPerChar + j] = (byte) (chars[i] >>> (8 * (bytesPerChar - 1 - j)));
}
return toReturn;
}
public static String getString(byte[] bytes, int bytesPerChar)
{
char[] chars = new char[bytes.length / bytesPerChar];
for (int i = 0; i < chars.length; i++)
{
for (int j = 0; j < bytesPerChar; j++)
{
int shift = (bytesPerChar - 1 - j) * 8;
chars[i] |= (0x000000FF << shift) & (((int) bytes[i * bytesPerChar + j]) << shift);
}
}
return new String(chars);
}
}
As #Per Wiklander pointed out, this doesn't truely support UTF-8. Here is a true UTF-8 decoder ported from C here
private static class UTF8Decoder
{
final byte[] the_input;
int the_index, the_length;
protected UTF8Decoder( byte[] bytes )
{
super();
this.the_input = bytes;
this.the_index = 0;
this.the_length = bytes.length;
}
/*
Get the next byte. It returns UTF8_END if there are no more bytes.
*/
int get()
{
int c;
c = the_input[the_index] & 0xFF;
the_index += 1;
return c;
}
/*
Get the 6-bit payload of the next continuation byte.
Return UTF8_ERROR if it is not a contination byte.
*/
int cont()
{
int c = get();
if( (c & 0xC0) == 0x80 )
return (c & 0x3F);
else
throw new IllegalArgumentException( "Failed to pass strict UTF-8" );
}
CharSequence getStringUTF8()
{
StringBuilder sb = new StringBuilder( the_input.length ); // allocate a maximum size
while( the_index < the_length )
{
int c; /* the first byte of the character */
int r; /* the result */
c = get();
/*
Zero continuation (0 to 127)
*/
if( (c & 0x80) == 0 )
{
sb.append( (char) c );
}
/*
One continuation (128 to 2047)
*/
else if( (c & 0xE0) == 0xC0 )
{
int c1 = cont();
if( c1 >= 0 )
{
r = ((c & 0x1F) << 6) | c1;
if( r >= 128 )
sb.append( (char) r );
else
throw new IllegalArgumentException();
}
}
/*
Two continuation (2048 to 55295 and 57344 to 65535)
*/
else if( (c & 0xF0) == 0xE0 )
{
int c1 = cont();
int c2 = cont();
if( (c1 | c2) >= 0 )
{
r = ((c & 0x0F) << 12) | (c1 << 6) | c2;
if( r >= 2048 && (r < 55296 || r > 57343) )
sb.append( (char) r );
else
throw new IllegalArgumentException();
}
}
/*
Three continuation (65536 to 1114111)
*/
else if( (c & 0xF8) == 0xF0 )
{
int c1 = cont();
int c2 = cont();
int c3 = cont();
if( (c1 | c2 | c3) >= 0 )
sb.append( (char) ((((c & 0x0F) << 18) | (c1 << 12) | (c2 << 6) | c3) + 65536) ); // TODO this might not work as it is being cast to a char
}
else
throw new IllegalArgumentException( "Failed strict UTF8 parsing" );
}
return sb;
}
}
Good question. I didn't realize it before.
as far as I know there is only 2 main method that convert byte array to String
You mentioned it
The fantastic way with java.io package that you can't use it on client-side
Here is mine implementation. I think it may be helpful to you
public static String convertByteArrayToString(byte[] byteArray) {
String s = "";
for (int i = 0; i < byteArray.length; i++) {
s += (char) (byteArray[i]);
}
return s;
}
You can test it :
byte[] byteArray = new byte[] { 87, 79, 87, 46, 46, 46 };
System.out.println(convertByteArrayToString(byteArray));
System.out.println(new String(byteArray));