Android巨量字符串输出

前言

最近公司接入一个项目,红外遥控,就是用手机去控制机顶盒播放节目,截图所示。领导让我去对接歌华有线机顶盒一个红外数据。


歌华有线.jpg

问题

我拿着SDK对比api,很快找到获取特定id下的机顶盒红外数据方法,返回值里面的data封装在SDK里面无法直接tosring的形式直接输出数据,最后只能用Gson去转格式。如下gson换换公式,当时转过之后我想先Log看一下数据,然后我复制Log日志放在在线json格式化上查看,结果显示格式化错误。我想着是不是因为接口返回的json数据过大的原因导致无法使用Gson去解析的原因,后来又使用fastjson,然后还有超大json解析,最后打印的日志都是不全的,最后上网查到AS里面日志一行最多显示4000个字符。

解决问题

1.日志字符拼接

在网上找到关于过长日志打印限制问题,超过4000个字符之后通过换行的形式,然后把所有的日志再进行拼接起来输出。

public static void LoggerE(String tag, String bodyMsg) {  //信息太长,分段打印
        //因为String的length是字符数量不是字节数量所以为了防止中文字符过多,
        //  把4*1024的MAX字节打印长度改为2001字符数
        if (bodyMsg.length() > 4000) {
            for (int i = 0; i < bodyMsg.length(); i += 4000) {
                //当前截取的长度<总长度则继续截取最大的长度来打印
                if (i + 4000 < bodyMsg.length()) {
                    Log.e(tag + i, bodyMsg.substring(i, i + 4000));
                } else {
                    //当前截取的长度已经超过了总长度,则打印出剩下的全部信息
                    Log.e(tag + i, bodyMsg.substring(i, bodyMsg.length()));
                }
            }
        } else {
            //直接打印
            Log.e(tag, bodyMsg);
        }
    }

通过日志换行显示,然后又通过字符的拼接,但是通过在线json发现还是出现格式化问题。

2.Textview复制粘贴

昨天晚上不知道什么时候想到用日志输出数据太麻烦还容易出错,那就用TextView来显示数据,然后通过复制粘贴的形式输出。TextView复制粘贴的方式有如下两种:

第一种

在xml中直接设置属性:android:textIsSelectable=”true”

  • 这种方式要求sdk>11
第二种

直接使用TextView, 然后在代码里给TextView添加OnLongClickListener事件,长按时弹出自定义 “复制” 菜单(比如结合 PopupWindow做弹出菜单). 点击”复制” 就去获取TextView的内容.

ClipboardManager cmb = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
cmb.setText(content.trim()); //将内容放入粘贴管理器,在别的地方长按选择"粘贴"即可
cm.getText();//获取粘贴信息

还有一个问题就是系统自带的Textview不会自动换行,我从网上找到一个关于自定义TextView自动换行的,如下:

public class JustifyTextView extends TextView {

    private int mLineY;
    private int mViewWidth;
    public static final String TWO_CHINESE_BLANK = "  ";

    public JustifyTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        TextPaint paint = getPaint();
        paint.setColor(getCurrentTextColor());
        paint.drawableState = getDrawableState();
        mViewWidth = getMeasuredWidth();
        String text = getText().toString();
        mLineY = 0;
        mLineY += getTextSize();
        Layout layout = getLayout();
        // layout.getLayout()在4.4.3出现NullPointerException
        if (layout == null) {
            return;
        }
        Paint.FontMetrics fm = paint.getFontMetrics();
        int textHeight = (int) (Math.ceil(fm.descent - fm.ascent));
        textHeight = (int) (textHeight * layout.getSpacingMultiplier() + layout.getSpacingAdd());
        for (int i = 0; i < layout.getLineCount(); i++) {
            int lineStart = layout.getLineStart(i);
            int lineEnd = layout.getLineEnd(i);
            float width = StaticLayout.getDesiredWidth(text, lineStart, lineEnd, getPaint());
            String line = text.substring(lineStart, lineEnd);
            if (needScale(line) && i < layout.getLineCount() - 1) {
                drawScaledText(canvas, lineStart, line, width);
            } else {
                canvas.drawText(line, 0, mLineY, paint);
            }
            mLineY += textHeight;
        }
    }

    private void drawScaledText(Canvas canvas, int lineStart, String line, float lineWidth) {
        float x = 0;
        if (isFirstLineOfParagraph(lineStart, line)) {
            String blanks = "  ";
            canvas.drawText(blanks, x, mLineY, getPaint());
            float bw = StaticLayout.getDesiredWidth(blanks, getPaint());
            x += bw;
            line = line.substring(3);
        }
        int gapCount = line.length() - 1;
        int i = 0;
        if (line.length() > 2 && line.charAt(0) == 12288 && line.charAt(1) == 12288) {
            String substring = line.substring(0, 2);
            float cw = StaticLayout.getDesiredWidth(substring, getPaint());
            canvas.drawText(substring, x, mLineY, getPaint());
            x += cw;
            i += 2;
        }
        float d = (mViewWidth - lineWidth) / gapCount;
        for (; i < line.length(); i++) {
            String c = String.valueOf(line.charAt(i));
            float cw = StaticLayout.getDesiredWidth(c, getPaint());
            canvas.drawText(c, x, mLineY, getPaint());
            x += cw + d;
        }
    }

    private boolean isFirstLineOfParagraph(int lineStart, String line) {
        return line.length() > 3 && line.charAt(0) == ' ' && line.charAt(1) == ' ';
    }

    private boolean needScale(String line) {
        if (line == null || line.length() == 0) {
            return false;
        } else {
            return line.charAt(line.length() - 1) != '\n';
        }
    }
}

通过TextView方式获取的string数据,还需要粘贴操作配合输出数据,我试过几种方式,在此分享一下,因为数据过长,普通QQ还有其他软件都不能粘贴全部数据,如果手机里面有wps的可以直接把数据粘贴输出,第二种是office,我手机的office不支持粘贴,不过因为小米手机的搜狗输入法自带粘贴板,通过粘贴板粘贴数据输出。

3.Txt文件写入

思前想后,总感觉前面的方式都不是特别好,过程都比较繁琐,因为我本来是要输出txt文件,所以想到能不能直接把string字符串直接转为txt文本。如下有两种写入方式:

第一种写入:
/**
     * string转换txt
     *
     * @param filePath 文件路径
     * @param fileName 文件名
     * @param str      输出文本
     */
    public void stringToTxt(String filePath, String fileName, String str) {
        try {
            //首先要去创建文件
            makeFilePath(filePath, fileName);

            FileWriter fw = new FileWriter(filePath + fileName);
            //SD卡中的路径
            fw.flush();
            fw.write(str);
            fw.close();
            Log.e("TAG", "写入成功");
        } catch (Exception e) {
            Log.e("TAG", "异常:" + e.getMessage());
            e.printStackTrace();
        }
    }

第二种写入:
/**
     * 写入文件
     *
     * @param strcontent 字符串
     * @param filePath   路径
     * @param fileName   文件名
     */
    public void writeTxtToFile(String strcontent, String filePath, String fileName) {
        //生成文件夹之后,再生成文件,不然会出错
        makeFilePath(filePath, fileName);

        String strFilePath = filePath + fileName;
        // 每次写入时,都换行写
        String strContent = strcontent + "\r\n";
        try {
            File file = new File(strFilePath);
            if (!file.exists()) {
                Log.d("TestFile", "Create the file:" + strFilePath);
                file.getParentFile().mkdirs();
                file.createNewFile();
            }
            RandomAccessFile raf = new RandomAccessFile(file, "rwd");
            raf.seek(file.length());
            raf.write(strContent.getBytes());
            raf.close();
        } catch (Exception e) {
            Log.e("TestFile", "Error on write File:" + e);
        }
    }

下面是创建文件夹以及文件的方法:

  • 创建文件夹
/**
     * 创建文件夹
     *
     * @param filePath
     */
    public static void makeRootDirectory(String filePath) {
        File file = null;
        try {
            file = new File(filePath);
            if (!file.exists()) {
                file.mkdir();
            }
        } catch (Exception e) {
            Log.i("error:", e + "");
        }
    }

  • 创建文件
/**
     * 创建文件
     *
     * @param filePath
     * @param fileName
     * @return
     */
    public File makeFilePath(String filePath, String fileName) {
        File file = null;
        makeRootDirectory(filePath);
        try {
            file = new File(filePath + fileName);
            if (!file.exists()) {
                file.createNewFile();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return file;
    }
还有一点需要主要,对于json特殊字符的转换,有时候会出现转换错误问题,建议使用fastjson去转换。*

你可能感兴趣的:(Android巨量字符串输出)