2019年3月5日 星期二

不同系統的換行符號

str.replace(/(\r\n|\n)/, '')


|一、概念:

換行符‘\n’和回車符‘\r’

(1)換行符就是另起一行  — ‘\n‘ 10 換行(newline)

(2)回車符就是回到一行的開頭 — ‘\r‘ 13 回車(return)

所以我們平時編寫檔案的回車符應該確切來說叫做回車換行符 

CR: 回車(Carriage Return) \r
LF: 換行(Line Feed) \n

二、應用:
(1)在微軟的MS-DOS和Windows中,使用“回車CR(‘\r’)”和“換行LF(‘\n’)”兩個字元作為換行符;
(2)Windows系統裡面,每行結尾是 回車 換行(CR LF),即“\r\n”;
(3)Unix系統裡,每行結尾只有 換行LF,即“\n”;
(4)Mac系統裡,每行結尾是 回車CR 即’\r’。
Mac OS 9 以及之前的系統的換行符是 CR,從 Mac OS X (後來改名為“OS X”)開始的換行符是 LF即‘\n’,和Unix/Linux統一了。
三、影響:
(1)一個直接後果是,Unix/Mac系統下的檔案在Windows裡開啟的話,所有文字會變成一行;
(2)而Windows裡的檔案在Unix/Mac下開啟的話,在每行的結尾可能會多出一個^M符號。
(3)Linux儲存的檔案在windows上用記事本看的話會出現黑點。
四、可以相互轉換:
在linux下,命令unix2dos 是把linux檔案格式轉換成windows檔案格式,命令dos2unix 是把windows格式轉換成linux檔案格式。
在不同平臺間使用FTP軟體傳送檔案時, 在ascii文字模式傳輸模式下, 一些FTP客戶端程式會自動對換行格式進行轉換. 經過這種傳輸的檔案位元組數可能會發生變化.
 如果你不想ftp修改原檔案, 可以使用bin模式(二進位制模式)傳輸文字。
一個程式在windows上執行就生成CR/LF換行格式的文字檔案,而在Linux上執行就生成LF格式換行的文字檔案。

2019年2月26日 星期二

拖曳一個小方塊.......不錯用

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <script src="./js_lib/jquery-3.3.1.js"></script>
    <style>
        * {
            padding: 0;
            margin: 0;
            box-sizing: border-box;
        }

        body {
            position: relative;
        }

        div.container_1 {
            height: 1000px;
            background-color: #ffc;
            position: relative;
        }

        #moveEvent {
            position: absolute;
            left: 0;
            top: 0;
            width: 100%;
            height: 100%;
            border: 1px dashed;
            z-index: 99999;
            display: none;
            user-select: none;
            opacity: 0;
        }

        #box_1 {
            width: 100px;
            height: 100px;
            position: absolute;
            top: 50px;
            left: 100px;
            z-index: 100;
            background-color: #00F;
            user-select: none;
        }
    </style>
</head>

<body>
    <div id="moveEvent">
        <!-- 全螢幕的畫布 -->
    </div>
    <div class="container_1">
        <p id="box_1">
            box
        </p>
    </div>
    <script>

        // screen 與 #box_1 的座標差
        let topOffset;
        let leftOffset;
        let callback;


        $('#box_1').on('mousedown', function (e) {
            console.dir(e);


            let { left, top } = $(this).position();

            topOffset = top - e.screenY;
            leftOffset = left - e.screenX;
            //-----------------------
            callback = (function (leftOffset, topOffset, x, y) {
                let left = x + leftOffset;
                let top = y + topOffset;

                $('#box_1').css({
                    top: top,
                    left: left
                });
            }).bind(this, leftOffset, topOffset);
            //-----------------------
            $('#moveEvent').css('display', 'block');
        });

        $('#moveEvent').on('mousemove', function (e) {
            console.log('offset:(%s, %s)', e.offsetX, e.offsetY);
            console.log('screen(%s, %s)', e.screenX, e.screenY);

            if(callback){
                callback(e.screenX, e.screenY);
            }
        });

        $('#moveEvent').on('mouseup', function () {
            callback = undefined;
            $('#moveEvent').css('display', '');
        });
    </script>
</body>

</html>

2019年2月25日 星期一

yahoo serialize

/*
Copyright (c) 2014, Yahoo! Inc. All rights reserved.
Copyrights licensed under the New BSD License.
See the accompanying LICENSE file for terms.
*/

'use strict';

// Generate an internal UID to make the regexp pattern harder to guess.
var UID                 = Math.floor(Math.random() * 0x10000000000).toString(16);
var PLACE_HOLDER_REGEXP = new RegExp('"@__(F|R|D)-' + UID + '-(\\d+)__@"', 'g');

var IS_NATIVE_CODE_REGEXP = /\{\s*\[native code\]\s*\}/g;
var UNSAFE_CHARS_REGEXP   = /[<>\/\u2028\u2029]/g;

// Mapping of unsafe HTML and invalid JavaScript line terminator chars to their
// Unicode char counterparts which are safe to use in JavaScript strings.
var ESCAPED_CHARS = {
    '<'     : '\\u003C',
    '>'     : '\\u003E',
    '/'     : '\\u002F',
    '\u2028': '\\u2028',
    '\u2029': '\\u2029'
};

function escapeUnsafeChars(unsafeChar) {
    return ESCAPED_CHARS[unsafeChar];
}

module.exports = function serialize(obj, options) {
    options || (options = {});

    // Backwards-compatability for `space` as the second argument.
    if (typeof options === 'number' || typeof options === 'string') {
        options = {space: options};
    }

    var functions = [];
    var regexps   = [];
    var dates     = [];

    // Returns placeholders for functions and regexps (identified by index)
    // which are later replaced by their string representation.
    function replacer(key, value) {
        if (!value) {
            return value;
        }

        // If the value is an object w/ a toJSON method, toJSON is called before
        // the replacer runs, so we use this[key] to get the non-toJSONed value.
        var origValue = this[key];
        var type = typeof origValue;

        if (type === 'object') {
            if(origValue instanceof RegExp) {
                return '@__R-' + UID + '-' + (regexps.push(origValue) - 1) + '__@';
            }

            if(origValue instanceof Date) {
                return '@__D-' + UID + '-' + (dates.push(origValue) - 1) + '__@';
            }
        }

        if (type === 'function') {
            return '@__F-' + UID + '-' + (functions.push(origValue) - 1) + '__@';
        }

        return value;
    }

    var str;

    // Creates a JSON string representation of the value.
    // NOTE: Node 0.12 goes into slow mode with extra JSON.stringify() args.
    if (options.isJSON && !options.space) {
        str = JSON.stringify(obj);
    } else {
        str = JSON.stringify(obj, options.isJSON ? null : replacer, options.space);
    }

    // Protects against `JSON.stringify()` returning `undefined`, by serializing
    // to the literal string: "undefined".
    if (typeof str !== 'string') {
        return String(str);
    }

    // Replace unsafe HTML and invalid JavaScript line terminator chars with
    // their safe Unicode char counterpart. This _must_ happen before the
    // regexps and functions are serialized and added back to the string.
    str = str.replace(UNSAFE_CHARS_REGEXP, escapeUnsafeChars);

    if (functions.length === 0 && regexps.length === 0 && dates.length === 0) {
        return str;
    }

    // Replaces all occurrences of function, regexp and date placeholders in the
    // JSON string with their string representations. If the original value can
    // not be found, then `undefined` is used.
    return str.replace(PLACE_HOLDER_REGEXP, function (match, type, valueIndex) {
        if (type === 'D') {
            return "new Date(\"" + dates[valueIndex].toISOString() + "\")";
        }

        if (type === 'R') {
            return regexps[valueIndex].toString();
        }

        var fn           = functions[valueIndex];
        var serializedFn = fn.toString();

        if (IS_NATIVE_CODE_REGEXP.test(serializedFn)) {
            throw new TypeError('Serializing native function: ' + fn.name);
        }

        return serializedFn;
    });
}

2019年2月13日 星期三

java swing 刊誤

p525>> 
import java.awt.event.*;
import java.awt.Window;

public class BasicWindowMonitor extends WindowAdapter {

  public void windowClosing(WindowEvent e) {
    Window w = e.getWindow();
    w.setVisible(false);
    w.dispose();
    System.exit(0);
  }
}

2019年2月9日 星期六

node.js 路徑

// 專案目錄位置
const root = fs.realpathSync('./');

require(`${root}/node_modules/..........`);

 

process.cwd()

 

2019年2月3日 星期日

java 取得物件資訊

static void getClassInfo(Object o) {
        Class c = o.getClass();

        // 取得套件代表物件
        Package p = c.getPackage();

        out.printf("package %s;%n", p.getName());

        // 取得型態修飾,像是public、final
        int m = c.getModifiers();

        out.print(Modifier.toString(m) + " ");
        // 如果是介面
        if (Modifier.isInterface(m)) {
            out.print("interface ");
        } else {
            out.print("class ");
        }

        out.println(c.getName() + " {");
        //-----------------------
        // 取得宣告的資料成員代表物件
        Field[] fields = c.getDeclaredFields();
        for (Field field : fields) {
            // 顯示權限修飾,像是public、protected、private
            out.print("\t"
                    + Modifier.toString(field.getModifiers()));
            // 顯示型態名稱
            out.print(" "
                    + field.getType().getName() + " ");
            // 顯示資料成員名稱
            out.println(field.getName() + ";");
        }
       
        out.println("----------------------");
        //-----------------------
        Method[] methods = c.getDeclaredMethods();
        for (Method method : methods) {
            // 顯示權限修飾,像是public、protected、private
            out.print("\t"
                    + Modifier.toString(
                            method.getModifiers()));
            // 顯示返回值型態名稱
            out.print(" "
                    + method.getReturnType().getName() + " ");
            // 顯示方法名稱
            out.println(method.getName() + "();");
        }
        out.println("}");
    }

2019年2月2日 星期六

操控點位移(不錯的版本)

<pre>
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style media="screen">
        *{
            padding: 0;
            margin: 0;
            box-sizing: border-box;
        }

        .main_container{
            width: 400px;
            height:300px;
            background-color: #FCC;
            position: relative;
        }

        .symbol {
            width: 100%;
            height: 100%;
        }

        .operator{
            position: absolute;
            left: 0;
            top: 0;
            width: 100%;
            height: 100%;
        }

        p.box{
            position: absolute;
            left: 0;
            top: 0;
            width: 20px;
            height: 20px;
            background-color: #666;
        }
    </style>
    <script src="./js_lib/jquery-3.3.1.min.js" charset="utf-8"></script>

</head>

<body>
    <div>
        <button type="button" onclick=t_1()>go</button>
    </div>
    <div class="main_container">
        <div id="symbol" class="symbol">

        </div>
        <div id="operator" class="operator">
            <p class="box" id="box_1"></p>

        </div>

    </div>
    <script>
        function V(){
            this.symbol;
            this.operator;
            this.box;

            this.box_click_left;
            this.box_click_top;

            this.__construct();
        };

        (function(){
            this.__construct = function(){
                debugger;
                this.symbol = document.querySelector('#symbol');
                this.operator = document.querySelector('#operator');
                this.box = document.querySelector('#box_1');



                $(this.box).on('mousedown', (function(e){
                    this.event_1(e);
                }).bind(this));


                $(this.operator).on('mouseup', (function(e){
                    this.event_2(e);
                }).bind(this));

            };
            //----------------------------
            this.event_1 = function(e){
                // debugger;

                this.box_click_left = e.offsetX;
                this.box_click_top = e.offsetY;

                $(this.box).appendTo(this.symbol);

                $(this.operator).on('mousemove', (function(e){
                    this.event_3(e);
                }).bind(this));
            };
            //----------------------------
            this.event_2 = function(e){
                $(this.operator).off('mousemove');
                $(this.box).appendTo(this.operator);
            };
            //----------------------------

            this.event_3 = function(e){

                console.log('(%s, %s)', e.offsetX, e.offsetY);

                let x= e.offsetX - this.box_click_left;
                let y = e.offsetY - this.box_click_top;

                $(this.box).css({
                    left: x,
                    top: y
                });

            };
        }).call(V.prototype);

        new V();
    </script>
</body>

</html>
</pre>

2019年1月24日 星期四

pipe

https://www.npmjs.com/package/multipipe
https://github.com/zoubin/streamify-your-node-program

http://www.xiedacon.com/2017/08/11/Node.js%E6%BA%90%E7%A0%81%E8%A7%A3%E6%9E%90-pipe%E5%AE%9E%E7%8E%B0/#Node-js%E6%BA%90%E7%A0%81%E8%A7%A3%E6%9E%90-pipe%E5%AE%9E%E7%8E%B0

-----------------------------------------------------------------------

const _ = require("underscore");
require("underscore_extension")(_);

const $path = require("path");
const $fs = require('fs');
const $zlib = require('zlib');

http();

function http() {

    let server = require("http").createServer(async function (req, resp) {

        resp.writeHead(200, {
            'Content-Type': 'image/jpg',
            'content-encoding': 'gzip'
        });


        let _path = $path.resolve(__dirname, './images/plane_1.jpg');

        let reader = $fs.createReadStream(_path);
        reader = reader.pipe($zlib.createGzip());
        await pipe(reader, resp);

        resp.end();
    });
    server.listen(8081);
}

function _error(res) {
    res.writeHead(200, {
        'Content-Type': 'text/html'
    });
    console.log('error...')
    res.end('<h1>error</h1>');
}


function pipe(reader, writer, size) {

    let def = _.deferred();

    reader.on('readable', function () {
        // 採用靜態模式
        console.log('----------readable----------------');
        write();
    });

    reader.on('data', function (chunk) {
        // reader.read() 會進來此
        console.log('on data(%s)', chunk.length);
    });

    writer.on('drain', function () {
        console.log('drain..........');

        let data;

        // 讀取之未讀完的記憶體
        if (!write(true)) {
            return;
        }

        console.log('舊的讀取完');
        reader.resume();
    });

    reader.on('end', function () {
        console.log('end');
        def.resolve();
    });
    //----------------------------

    function write(noPause) {
        console.log('....write')
        while (true) {
            console.log('read(%s)', (noPause ? 'flush' : 'ok'));
            let data = reader.read(size);

            if (data === null) {
                console.log('read end');
                break;
            } else {
                if (writer.write(data) === false) {
                    console.log('too much pause');

                    if (!noPause) {
                        console.log('pause...');
                        reader.pause();
                    }

                    return false;
                }
            }
        }
        return true;
    }

    //----------------------------
    return def.promise();
}










2019年1月19日 星期六

node.js stream.pipe

Stream.prototype.pipe = function(dest, options) {
  var source = this;
  source.on('data', function (chunk) {
    if (dest.writable) {
      if (false === dest.write(chunk) && source.pause) {
        source.pause();
      }
    }
  });

  dest.on('drain',   function () {
    if (source.readable && source.resume) {
      source.resume();
    }
  });

  dest.emit('pipe', source);

  // Allow for unix-like usage: A.pipe(B).pipe(C)
  return dest;
};

2019年1月18日 星期五

node.js 進程池

const cp = require('child_process')

function doWork(job, callback) {
    // TODO worker 是 工作进程,下一步进行实现
    let child = cp.fork('./worker')
    // 用来跟踪回调的执行状态,防止出现多次回调调用
    let cbTriggered = false;

    child.once('error', function (err) {
        if (!cbTriggered) {
            callback(err)
            cbTriggered = true;
        }
        // 异常错误时,杀死子进程
        child.kill();
    })
        .once('exit', function (code, signal) {
            if (!cbTriggered) {
                callback(new Error('Child exited with code: ' + code));
            }
        })
        .once('message', function (result) {
            callback(null, result)
            cbTriggered = true;
        })
        .send(job);
}

//--------------------------------------
// pooler.js

const cp = require('child_process');
// 取到cpu 数量
const cpus = require('os').cpus().length;

module.exports = function (workModule) {

    // 当没有空闲的cpu时,用来存放任务队列
    let awaiting = [];
    // 存放准备就绪的工作进程
    let readyPool = [];
    // 存放现有的工作者进程的数量
    let poolSize = 0;

    return function doWork(job, callback) {

        // 如果没有空闲的工作进程并且工作进程达到了限制,就把后续任务放入队列等待执行
        if (!readyPool.length && poolSize > cpus) {
            return awaiting.push([doWork, job, callback])
        }

        // 获取下一个可用的子进程或者fork一个新的进程并增加池子大小
        let child = readyPool.length
            ? readyPool.shift()
            : (poolSize++ , cp.fork(workModule));

        let cbTriggered = false;

        // 移除子进程上的所有监听,保证每一个子进程每次只有一个监听
        child
            .removeAllListeners()
            .once('error', function (err) {
                if (!cbTriggered) {
                    callback(err)
                    cbTriggered = true;
                }
                child.kill();
            })
            .once('exit', function (code, signal) {

                if (!cbTriggered) {
                    callback(new Error('Child exited with code: ' + code));
                }

                poolSize--;
                // 如果子进程由于某种原因退出,保证在readyPool中也被移除了
                let childIdx = readyPool.indexOf(child);
                if (childIdx > -1) {
                    readyPool.splice(childIdx, 1);
                }

            })
            .once('message', function (result) {
                callback(null, result)

                cbTriggered = true;

                // 把空闲的子进程再次放入readyPool,等待接下来的任务
                readyPool.push(child);
                if (awaiting.length) {
                    setImmediate.apply(null, awaiting.shift());
                }
            })
            .send(job);
    }
}

2019年1月16日 星期三

node.js http 讀取 stream

function pstreamPipe(path, callback, code){
    return (streamPipe(path, callback, code)[0]);
}


function streamPipe(path, callback, code) {
    let def = _.deferred();


    let stream = require("fs").createReadStream(path);
    if (code) {
        stream.setEncoding(code);
    }

    stream.on('data', function (data) {
        callback(data);
    });

    stream.on('error', function (err) {
        def.reject(err);
    });

    stream.on('end', function () {
        def.resolve();
    });

    return [def.promise(), stream];
}

swing 的組織想法

// 中間協調者
public class Observeable<T> {
    // 要通知的組件
    public ArrayList<Observe> elements;
   
    public void emit(String eventName, T data){
       
    }
}

public interface Observe<T> {
   
    public void on(String eventName);
   
    public void off(String eventName);
   
    public void notify(String eventName, T data);
}

public class Element<T, E> implements Observe<E> {
    // swing 元件
    public T x;

    @Override
    public void on(String eventName) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    @Override
    public void off(String eventName) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    @Override
    public void notify(String eventName, E data) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }  
}