精华内容
下载资源
问答
  • 用买票例子讲讲多线程安全问题

    千次阅读 2014-08-31 23:35:25
    在javase中多线程安全问题,买票的例子几乎是都会到,今天

    在javase中多线程安全问题,买票的例子几乎是都会讲到,今天就以买票的程序来简单分析下java多线程安全问题的产生以及解决方案

    先看程序代码:

    public class ThreadTest1 {
    /**
    * @param args
    */
    public static void main(String[] args) {
    //这是二个线程操作同一个对象 一般都是实现Runnable接口
    ThreadDemo t = new ThreadDemo();
    Thread t1 = new Thread(t);
    Thread t2 = new Thread(t);
    Thread t3 = new Thread(t);
    Thread t4 = new Thread(t);

    t1.start();
    t2.start();
    t3.start();
    t4.start();

    }


    }
    class ThreadDemo implements  Runnable {
    String str = "";
    int num=100;
    public void run() {
    while(true){
    if(num>0){
    try {
    Thread.sleep(10);
    } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    System.out.println(Thread.currentThread().getName()+"-----"+"num="+num--);
    }
    }
    }
    }


    打印结果如图:


    通过打印的结果发现出现了0 -1 -2,这肯定不是我们想要的结果,现在就分析问题出现的原因


    通过例子分析发现多线程安全产生的原因有

    1:多线程操作共享的数据(票数),因为四个线程都是操作一个对象,而对象分配在堆内存中,操作的就是它的成员变量是

    2:操作共享数据的线程有多条,在例子中体现就是if()语句 和输出语句


    总结:当一个线程在执行操作共享的多条代码过程中,其他线程参与了运算,就会导致安全问题的产生!


    展开全文
  • dbus介绍与例子

    万次阅读 多人点赞 2015-08-08 16:50:45
    D-bus是一个进程间通信的工具,优点在这里赘述。  网上很多关于dbus的帖子都是基于dbus-glib或者QT D-bus的,直接使用dbus的教程比较少。也难怪,因为连D-bus的官网都说:"If you use this low-level API ...

      D-bus是一个进程间通信的工具,优点不在这里赘述。


      网上很多关于dbus的帖子都是基于dbus-glib或者QT D-bus的,直接使用dbus的教程比较少。也难怪,因为连D-bus的官网都说:"If you use this low-level API directly, you're signing up for some pain."

      但实际上,直接使用D-bus也没有想象中难。本文将对直接使用D-bus做一个介绍。


    本文参考了其他一些网站的帖子或者介绍

    官网:http://www.freedesktop.org/wiki/Software/dbus/

    经典例子:http://www.matthew.ath.cx/articles/dbus

    不错的帖子:http://blog.csdn.net/flowingflying/article/details/4527634


    一、概念介绍

      这里虽然说是概念介绍,其实只是我个人对D-bus的一个理解,不一定完整准确。

     1.首先,D-bus可以分成三部分来看,

    (1)dbus-daemon,一个dbus的后台守护程序,用于多个应用之间消息的转发;

    (2)libdbus.so,dbus的功能接口,当你的程序需要使用dbus时,其实就是调用libdbus.so里面的接口;

    (3)高层封装,如dbus-glib和QT D-bus,这些其实都对D-bus的再封装,让你使用起来更方便。

      从D-bus官网下载到源码,其实只包含上面所说的1和2两部分,libdbus.so里面的接口也就是官网说的low-level API。


    2.关于address、bus name、path。。。。

      D-bus里面提到了一些概念,刚开始不太好理解,这些概念也很容易混淆。这些概念的权威解释可以看这里

      首先,运行一个dbus-daemon就是创建了一条通信的总线Bus。当一个application连接到这条Bus上面时,就产生了Connection。

      每个application里面会有不同的Object。这里Object的概念,可以简单地理解为C++里面一个类的实例。从D-bus的概念上说,通信双方是Object,不是application,一个application是可以包含很多个Object的。

      而一个Object里面又会有不同的Interface,这个Interface我把它理解为Object里面的一个类的成员。这些Interface其实是通信方式的集合。

      这里又牵扯出来一个通信方式,D-bus里面支持的通信方式有两种,一种叫signal,一种叫method。signal简单地讲,其实就是广播,就是一对多的通信方式,可以从app1向其他所有的app发消息,但其他的app是不会对signal进行回复的。method则是一对一的通信,一问一答。这种方式有点像远程调用,app1调用app2的method并传递参数给这个method,获取到这个method返回的结果。

      上面把D-bus通信里面的几个重要元素都介绍了一下,大概的关系是这样的:


      几个重要的元素之间的关系都画出来了,那么在程序里面怎么去标识这些元素呢?这里又提出来了一些名词address、bus name、path、Interface name。

    (1)address是用来标识dbus-daemon的。当一个dbus-daemon运行以后,其他的app该怎么连接到这个dbus-daemon,靠的就是address。address的格式要求像这样:unix:path=/var/run/dbus/system_bus_socket

    (2)bus name是用来标识application的。当一个app1连接上dbus-daemon以后,相当于有了一个Connection,但其他的app2、app3怎么找到app1,靠的就是bus name。这个bus name标识了app1的Connection,也就相当于标识了app1。bus name由两种,一种是已冒号开头的唯一标识,像:34-907这样;另一种是通用的标识,是方便人看的,像com.mycompany.TextEditor

    (3)path用于标识Object。当app1的Object1要跟app2的Object2通信时,Object1要和Object2通信时,就要告诉dbus-daemon,Object2的path。path的格式像这样,/com/mycompany/TextFileManager,已“/”开头。

    (4)每个Interface都会有自己的名字,也就是interface name,我们通过这个interface name就可以找到这个interface。interface name像这样org.freedesktop.Hal.Manager

    (5)Signal和Method也有自己的名字,这个名字没什么特别的格式要求,随便改个名字就可以了。

      官网上对这些标识列了一个表,如下:

    A... is identified by a(n)... which looks like... and is chosen by...
    Bus address unix:path=/var/run/dbus/system_bus_socket system configuration
    Connection bus name :34-907 (unique) or com.mycompany.TextEditor (well-known) D-Bus (unique) or the owning program (well-known)
    Object path /com/mycompany/TextFileManager the owning program
    Interface interface name org.freedesktop.Hal.Manager the owning program
    Member member name ListNames the owning program

    二、例子

    我在Matthew Johnson和恺风的例子基础上做了修改,如下:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <dbus/dbus.h>
    
    
    
    /*
     * listen, wait a call or a signal
     */
    #define DBUS_SENDER_BUS_NAME        "com.ty3219.sender_app"
    
    #define DBUS_RECEIVER_BUS_NAME      "com.ty3219.receiver_app"
    #define DBUS_RECEIVER_PATH          "/com/ty3219/object"
    #define DBUS_RECEIVER_INTERFACE     "com.ty3219.interface"
    #define DBUS_RECEIVER_SIGNAL        "signal"
    #define DBUS_RECEIVER_METHOD        "method"
    
    #define DBUS_RECEIVER_SIGNAL_RULE   "type='signal',interface='%s'"
    #define DBUS_RECEIVER_REPLY_STR     "i am %d, get a message"
    
    #define MODE_SIGNAL                 1
    #define MODE_METHOD                 2
    
    #define DBUS_CLIENT_PID_FILE        "/tmp/dbus-client.pid"
    
    /**
     *
     * @param msg
     * @param conn
     */
    void reply_method_call(DBusMessage *msg, DBusConnection *conn)
    {
        DBusMessage *reply;
        DBusMessageIter reply_arg;
        DBusMessageIter msg_arg;
        dbus_uint32_t serial = 0;
    
        pid_t pid;
        char reply_str[128];
        void *__value;
        char *__value_str;
        int __value_int;
    
        int ret;
    
        pid = getpid();
    
        //创建返回消息reply
        reply = dbus_message_new_method_return(msg);
        if (!reply)
        {
            printf("Out of Memory!\n");
            return;
        }
    
        //在返回消息中填入参数。
        snprintf(reply_str, sizeof(reply_str), DBUS_RECEIVER_REPLY_STR, pid);
        __value_str = reply_str;
        __value = &__value_str;
    
        dbus_message_iter_init_append(reply, &reply_arg);
        if (!dbus_message_iter_append_basic(&reply_arg, DBUS_TYPE_STRING, __value))
        {
            printf("Out of Memory!\n");
            goto out;
        }
    
        //从msg中读取参数,根据传入参数增加返回参数
        if (!dbus_message_iter_init(msg, &msg_arg))
        {
            printf("Message has NO Argument\n");
            goto out;
        }
    
        do
        {
            int ret = dbus_message_iter_get_arg_type(&msg_arg);
            if (DBUS_TYPE_STRING == ret)
            {
                dbus_message_iter_get_basic(&msg_arg, &__value_str);
                printf("I am %d, get Method Argument STRING: %s\n", pid,
                        __value_str);
    
                __value = &__value_str;
                if (!dbus_message_iter_append_basic(&reply_arg,
                        DBUS_TYPE_STRING, __value))
                {
                    printf("Out of Memory!\n");
                    goto out;
                }
            }
            else if (DBUS_TYPE_INT32 == ret)
            {
                dbus_message_iter_get_basic(&msg_arg, &__value_int);
                printf("I am %d, get Method Argument INT32: %d\n", pid,
                        __value_int);
    
                __value_int++;
                __value = &__value_int;
                if (!dbus_message_iter_append_basic(&reply_arg,
                        DBUS_TYPE_INT32, __value))
                {
                    printf("Out of Memory!\n");
                    goto out;
                }
            }
            else
            {
                printf("Argument Type ERROR\n");
            }
    
        } while (dbus_message_iter_next(&msg_arg));
    
        //发送返回消息
        if (!dbus_connection_send(conn, reply, &serial))
        {
            printf("Out of Memory\n");
            goto out;
        }
    
        dbus_connection_flush(conn);
    out:
        dbus_message_unref(reply);
    }
    
    /* 监听D-Bus消息,我们在上次的例子中进行修改 */
    void dbus_receive(void)
    {
        DBusMessage *msg;
        DBusMessageIter arg;
        DBusConnection *connection;
        DBusError err;
    
        pid_t pid;
        char name[64];
        char rule[128];
    
        const char *path;
        void *__value;
        char *__value_str;
        int __value_int;
    
        int ret;
    
        pid = getpid();
    
        dbus_error_init(&err);
        //创建于session D-Bus的连接
        connection = dbus_bus_get(DBUS_BUS_SESSION, &err);
        if (!connection)
        {
            if (dbus_error_is_set(&err))
                printf("Connection Error %s\n", err.message);
    
            goto out;
        }
    
        //设置一个BUS name
        if (0 == access(DBUS_CLIENT_PID_FILE, F_OK))
            snprintf(name, sizeof(name), "%s%d", DBUS_RECEIVER_BUS_NAME, pid);
        else
            snprintf(name, sizeof(name), "%s", DBUS_RECEIVER_BUS_NAME);
    
        printf("i am a receiver, PID = %d, name = %s\n", pid, name);
    
        ret = dbus_bus_request_name(connection, name,
                                DBUS_NAME_FLAG_REPLACE_EXISTING, &err);
        if (ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
        {
            if (dbus_error_is_set(&err))
                printf("Name Error %s\n", err.message);
    
            goto out;
        }
    
        //要求监听某个signal:来自接口test.signal.Type的信号
        snprintf(rule, sizeof(rule), DBUS_RECEIVER_SIGNAL_RULE, DBUS_RECEIVER_INTERFACE);
        dbus_bus_add_match(connection, rule, &err);
        dbus_connection_flush(connection);
        if (dbus_error_is_set(&err))
        {
            printf("Match Error %s\n", err.message);
            goto out;
        }
    
        while (1)
        {
            dbus_connection_read_write(connection, 0);
    
            msg = dbus_connection_pop_message(connection);
            if (msg == NULL)
            {
                sleep(1);
                continue;
            }
    
            path = dbus_message_get_path(msg);
            if (strcmp(path, DBUS_RECEIVER_PATH))
            {
                printf("Wrong PATH: %s\n", path);
                goto next;
            }
    
            printf("Get a Message\n");
            if (dbus_message_is_signal(msg, DBUS_RECEIVER_INTERFACE, DBUS_RECEIVER_SIGNAL))
            {
                printf("Someone Send me a Signal\n");
                if (!dbus_message_iter_init(msg, &arg))
                {
                    printf("Message Has no Argument\n");
                    goto next;
                }
    
                ret = dbus_message_iter_get_arg_type(&arg);
                if (DBUS_TYPE_STRING == ret)
                {
                    dbus_message_iter_get_basic(&arg, &__value_str);
                    printf("I am %d, Got Signal with STRING: %s\n",
                            pid, __value_str);
                }
                else if (DBUS_TYPE_INT32 == ret)
                {
                    dbus_message_iter_get_basic(&arg, &__value_int);
                    printf("I am %d, Got Signal with INT32: %d\n",
                            pid, __value_int);
                }
                else
                {
                    printf("Argument Type ERROR\n");
                    goto next;
                }
            }
            else if (dbus_message_is_method_call(msg, DBUS_RECEIVER_INTERFACE, DBUS_RECEIVER_METHOD))
            {
                printf("Someone Call My Method\n");
                reply_method_call(msg, connection);
            }
            else
            {
                printf("NOT a Signal OR a Method\n");
            }
    next:
            dbus_message_unref(msg);
        }
    
    out:
        dbus_error_free(&err);
    }
    
    /*
     * call a method
     */
    static void dbus_send(int mode, char *type, void *value)
    {
        DBusConnection *connection;
        DBusError err;
        DBusMessage *msg;
        DBusMessageIter arg;
        DBusPendingCall *pending;
        dbus_uint32_t serial;
    
        int __type;
        void *__value;
        char *__value_str;
        int __value_int;
        pid_t pid;
        int ret;
    
        pid = getpid();
    
        //Step 1: connecting session bus
        /* initialise the erroes */
        dbus_error_init(&err);
    
        /* Connect to Bus*/
        connection = dbus_bus_get(DBUS_BUS_SESSION, &err);
        if (!connection)
        {
            if (dbus_error_is_set(&err))
                printf("Connection Err : %s\n", err.message);
    
           goto out1;
        }
    
        //step 2: 设置BUS name,也即连接的名字。
        ret = dbus_bus_request_name(connection, DBUS_SENDER_BUS_NAME,
                                DBUS_NAME_FLAG_REPLACE_EXISTING, &err);
        if (ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
        {
            if (dbus_error_is_set(&err))
                printf("Name Err : %s\n", err.message);
    
            goto out1;
        }
    
    
        if (!strcasecmp(type, "STRING"))
        {
            __type = DBUS_TYPE_STRING;
            __value_str = value;
            __value = &__value_str;
        }
        else if (!strcasecmp(type, "INT32"))
        {
            __type = DBUS_TYPE_INT32;
            __value_int = atoi(value);
            __value = &__value_int;
        }
        else
        {
            printf("Wrong Argument Type\n");
            goto out1;
        }
    
    
        if (mode == MODE_METHOD)
        {
            printf("Call app[bus_name]=%s, object[path]=%s, interface=%s, method=%s\n",
                    DBUS_RECEIVER_BUS_NAME, DBUS_RECEIVER_PATH,
                    DBUS_RECEIVER_INTERFACE, DBUS_RECEIVER_METHOD);
    
            //针对目的地地址,创建一个method call消息。
            //Constructs a new message to invoke a method on a remote object.
            msg = dbus_message_new_method_call(
                    DBUS_RECEIVER_BUS_NAME, DBUS_RECEIVER_PATH,
                    DBUS_RECEIVER_INTERFACE, DBUS_RECEIVER_METHOD);
            if (msg == NULL)
            {
                printf("Message NULL");
                goto out1;
            }
    
            dbus_message_iter_init_append(msg, &arg);
            if (!dbus_message_iter_append_basic(&arg, __type, __value))
            {
                printf("Out of Memory!");
                goto out2;
            }
    
            //发送消息并获得reply的handle 。Queues a message to send, as with dbus_connection_send() , but also returns a DBusPendingCall used to receive a reply to the message.
            if (!dbus_connection_send_with_reply(connection, msg, &pending, -1))
            {
                printf("Out of Memory!");
                goto out2;
            }
    
            if (pending == NULL)
            {
                printf("Pending Call NULL: connection is disconnected ");
                goto out2;
            }
    
            dbus_connection_flush(connection);
            dbus_message_unref(msg);
    
            //waiting a reply,在发送的时候,已经获取了method reply的handle,类型为DBusPendingCall。
            // block until we receive a reply, Block until the pending call is completed.
            dbus_pending_call_block(pending);
            // get the reply message,Gets the reply, or returns NULL if none has been received yet.
            msg = dbus_pending_call_steal_reply(pending);
            if (msg == NULL)
            {
                printf("Reply Null\n");
                goto out1;
            }
    
            // free the pending message handle
            dbus_pending_call_unref(pending);
    
            // read the Arguments
            if (!dbus_message_iter_init(msg, &arg))
            {
                printf("Message has no Argument!\n");
                goto out2;
            }
    
            do
            {
                int ret = dbus_message_iter_get_arg_type(&arg);
                if (DBUS_TYPE_STRING == ret)
                {
                    dbus_message_iter_get_basic(&arg, &__value_str);
                    printf("I am %d, get Method return STRING: %s\n", pid,
                            __value_str);
                }
                else if (DBUS_TYPE_INT32 == ret)
                {
                    dbus_message_iter_get_basic(&arg, &__value_int);
                    printf("I am %d, get Method return INT32: %d\n", pid,
                            __value_int);
                }
                else
                {
                    printf("Argument Type ERROR\n");
                }
    
            } while (dbus_message_iter_next(&arg));
    
            printf("NO More Argument\n");
        }
        else if (mode == MODE_SIGNAL)
        {
            printf("Signal to object[path]=%s, interface=%s, signal=%s\n",
                    DBUS_RECEIVER_PATH, DBUS_RECEIVER_INTERFACE, DBUS_RECEIVER_SIGNAL);
    
            //步骤3:发送一个信号
            //根据图,我们给出这个信号的路径(即可以指向对象),接口,以及信号名,创建一个Message
            msg = dbus_message_new_signal(DBUS_RECEIVER_PATH,
                                DBUS_RECEIVER_INTERFACE, DBUS_RECEIVER_SIGNAL);
            if (!msg)
            {
                printf("Message NULL\n");
                goto out1;
            }
    
            dbus_message_iter_init_append(msg, &arg);
            if (!dbus_message_iter_append_basic(&arg, __type, __value))
            {
                printf("Out of Memory!");
                goto out2;
            }
    
            //将信号从连接中发送
            if (!dbus_connection_send(connection, msg, &serial))
            {
                printf("Out of Memory!\n");
                goto out2;
            }
    
            dbus_connection_flush(connection);
            printf("Signal Send\n");
        }
    
    out2:
        dbus_message_unref(msg);
    out1:
        dbus_error_free(&err);
    }
    
    static void usage(void)
    {
    #define USAGE "usage: ./dbus-client [send | receive] <param>\n" \
        "\treceive -- listen, wait a signal or a method call\n" \
        "\t\tif you want to test signal broadcast, run two receiver like this:\n" \
        "\t\trm -f /tmp/dbus-client.pid\n" \
        "\t\t./dbus-client receive &\n" \
        "\t\techo > /tmp/dbus-client.pid\n" \
        "\t\t./dbus-client receive &\n" \
        "\tsend [mode] [type] [value] -- send a signal or call a method\n" \
        "\t\tmode -- SIGNAL | METHOD\n" \
        "\t\ttype -- STRING | INT32\n" \
        "\t\tvalue -- string or number\n" \
        "\t\texample:\n" \
        "\t\t./dbus-client send SIGNAL STRING hello\n" \
        "\t\t./dbus-client send METHOD INT32 99\n" \
        "\n"
        printf(USAGE);
    }
    
    int main(int argc, char *argv[])
    {
        if (argc < 2)
        {
            usage();
            return -1;
        }
    
        if (!strcmp(argv[1], "receive"))
        {
            dbus_receive();
        }
        else if (!strcmp(argv[1], "send"))
        {
            if (argc < 5)
            {
                usage();
            }
            else
            {
                if (!strcasecmp(argv[2], "SIGNAL"))
                    dbus_send(MODE_SIGNAL, argv[3], argv[4]);
                else if (!strcasecmp(argv[2], "METHOD"))
                    dbus_send(MODE_METHOD, argv[3], argv[4]);
                else
                    usage();
            }
        }
        else
        {
            usage();
        }
    
        return 0;
    }
    
    

    三、运行

      想要运行上面的例子,还需要一些步骤。

    (1)运行dbus-daemon

    dbus-daemon的运行需要一个配置文件,这个配置文件稍微有点复杂,这里提供一个最简单的,无任何权限检查的例子debug-allow-all.conf

    <!-- Bus that listens on a debug pipe and doesn't create any restrictions -->
    
    <!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
     "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
    <busconfig>
      <type>session</type>
    
      <listen>unix:tmpdir=/tmp</listen>
    
      <standard_session_servicedirs />
    
      <policy context="default">
        <!-- Allow everything to be sent -->
        <allow send_destination="*" eavesdrop="true"/>
        <!-- Allow everything to be received -->
        <allow eavesdrop="true"/>
        <!-- Allow anyone to own anything -->
        <allow own="*"/>
        <allow user="*"/>
      </policy>
    
    </busconfig>
      

    执行下面的命令

    ./dbus-daemon --config-file=/path/to/debug-allow-all.conf --fork --print-address
    此时,dbus-daemon就会打印出一句类似这样的话

    unix:path=/tmp/dbus-UXeqD3TJHE,guid=88e7712c8a5775ab4599725500000051

    其实这个就是dbus-daemon的地址,我们需要把这个地址设置到环境变量里面,当你运行app的时候,libdbus.so就会读取这个环境变量,然后连接到这个dbus-daemon上。

    设置环境变量

    export DBUS_SESSION_BUS_ADDRESS=unix:path=/tmp/dbus-UXeqD3TJHE,guid=88e7712c8a5775ab4599725500000051

    (2)这个时候你就可以运行上面例子编译出来的程序

    ./dbus-app
    此时,会打印出一些参数信息。这个例子程序其实既可收也可以发,

    作为接收方时运行

    ./dbus-app receive &
    可以运行多个dbus-app作为接收方,这样测试signal时就可以看到多个dbus-app同时受到这个signal了。

    作为发送方时,发送signal


    ./dbus-app send SIGNAL STRING hello

    作为发送方时,调用method

    /dbus-app send METHOD INT32 30

      至此,一个dbus的例子就可以运行起来了,想详细了解这个例子需要自己去看例子的源码。


    展开全文
  • CreateFile用法和例子

    万次阅读 2012-01-17 13:44:21
    CreateFile用法和例子 函数原型:  HANDLE CreateFile(  LPCTSTR lpFileName, //指向文件名的指针  DWORD dwDesiredAccess, //访问模式(写/读)  DWORD dwShareMode, //共享模式  LPSECURITY_...

    CreateFile用法和例子

    函数原型: 

    HANDLE CreateFile(

      LPCTSTR lpFileName, //指向文件名的指针

      DWORD dwDesiredAccess, //访问模式(写/读)

      DWORD dwShareMode, //共享模式

      LPSECURITY_ATTRIBUTES lpSecurityAttributes, //指向安全属性的指针

      DWORD dwCreationDisposition, //如何创建

      DWORD dwFlagsAndAttributes, //文件属性

      HANDLE hTemplateFile //用于复制文件句柄

      );

      参数列表

      lpFileName String 要打开的文件的名字

      dwDesiredAccess Long 如果为 GENERIC_READ 表示允许对设备进行读访问;如果为 GENERIC_WRITE 表示允许对设备进行写访问(可组合使用);如果为零,表示只允许获取与一个设备有关的信息

      dwShareMode Long, 零表示不共享; FILE_SHARE_READ 和/或FILE_SHARE_WRITE 表示允许对文件进行共享访问

      lpSecurityAttributes SECURITY_ATTRIBUTES, 指向一个SECURITY_ATTRIBUTES结构的指针,定义了文件的安全特性(如果操作系统支持的话)

      dwCreationDisposition Long,下述常数之一:

      CREATE_NEW 创建文件;如文件存在则会出错

      CREATE_ALWAYS 创建文件,会改写前一个文件

      OPEN_EXISTING 文件必须已经存在。由设备提出要求

      OPEN_ALWAYS 如文件不存在则创建它

      TRUNCATE_EXISTING 讲现有文件缩短为零长度

      dwFlagsAndAttributes Long, 一个或多个下述常数

      FILE_ATTRIBUTE_ARCHIVE 标记归档属性

      FILE_ATTRIBUTE_COMPRESSED 将文件标记为已压缩,或者标记为文件在目录中的默认压缩方式

      FILE_ATTRIBUTE_NORMAL 默认属性

      FILE_ATTRIBUTE_HIDDEN 隐藏文件或目录

      FILE_ATTRIBUTE_READONLY 文件为只读

      FILE_ATTRIBUTE_SYSTEM 文件为系统文件

      FILE_FLAG_WRITE_THROUGH 操作系统不得推迟对文件的写操作

      FILE_FLAG_OVERLAPPED 允许对文件进行重叠操作

      FILE_FLAG_NO_BUFFERING 禁止对文件进行缓冲处理。文件只能写入磁盘卷的扇区块

      FILE_FLAG_RANDOM_ACCESS 针对随机访问对文件缓冲进行优化

      FILE_FLAG_SEQUENTIAL_SCAN 针对连续访问对文件缓冲进行优化

      FILE_FLAG_DELETE_ON_CLOSE 关闭了上一次打开的句柄后,将文件删除。特别适合临时文件

      也可在Windows NT下组合使用下述常数标记:

      SECURITY_ANONYMOUS, SECURITY_IDENTIFICATION, SECURITY_IMPERSONATION, SECURITY_DELEGATION, SECURITY_CONTEXT_TRACKING, SECURITY_EFFECTIVE_ONLY

      hTemplateFile Long, 如果不为零,则指定一个文件句柄。新文件将从这个文件中复制扩展属性

    返回值

      如执行成功,则返回文件句柄。

      INVALID_HANDLE_VALUE表示出错,会设置GetLastError。即使函数成功,但若文件存在,且指定了CREATE_ALWAYS 或 OPEN_ALWAYS,GetLastError也会设为ERROR_ALREADY_EXISTS

    (以上摘自百度百科)

    实例:

    1、直接在函数内指定文件地址:

    1. void playCEwav()
    2. {
    3. CHAR *pBuffer;
    4. DWORD RSize;
    5. int fileSize = 0;
    6. int i;
    7. HANDLE hOpenFile = (HANDLE)CreateFile(L"E:\\a.text", GENERIC_READ,FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL);
    8. if (hOpenFile == INVALID_HANDLE_VALUE)
    9. {
    10. hOpenFile = NULL;
    11. MessageBoxA(NULL, "Can not open the file", "Playwav", MB_OK);
    12. }
    13. fileSize = GetFileSize(hOpenFile, NULL);
    14. pBuffer = (CHAR *) malloc(fileSize);
    15. ReadFile(hOpenFile, pBuffer, fileSize, &RSize, NULL);
    16. //可将pBuffer显示在某区域或写入另一个文件来检查读出是否正确
    17. free(pBuffer);
    18. }

    2、把文件地址通过参数传入:

    1. void playwav(TCHAR * path)
    2. {
    3. CHAR *pBuffer;
    4. DWORD RSize;
    5. int fileSize = 0;
    6. int i;
    7. TCHAR szPath[100];
    8. memset(szPath, 0, sizeof(szPath));
    9. _tcscpy(szPath, path);
    10. HANDLE hOpenFile = (HANDLE)CreateFile(szPath, GENERIC_READ,FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL);
    11. if (hOpenFile == INVALID_HANDLE_VALUE)
    12. {
    13. hOpenFile = NULL;
    14. MessageBoxA(NULL, "Can not open the file", "Playwav", MB_OK);
    15. }
    16. fileSize = GetFileSize(hOpenFile, NULL);
    17. pBuffer = (CHAR *) malloc(fileSize);
    18. ReadFile(hOpenFile, pBuffer, fileSize, &RSize, NULL);
    19. free(pBuffer);
    20. }

    展开全文
  • 现在网上虽然讲解Unity3D动画的文章不少,但是却少很少带实际例子的。刚好我之前给美术做了个简单的例子,所以整理一下就共享给大家了。主要是做了两种动画,分别有例子,按空格可以改变动画。具体的制作过程不会...

    现在网上虽然讲解Unity3D动画的文章不少,但是却少很少带实际例子的。刚好我之前给美术做了个简单的例子,所以整理一下就共享给大家了。主要是做了两种动画,分别有例子,按空格可以改变动画。具体的制作过程不会非常详细(写的过程中,Generic被我写得有点详细了:),这里假设大家都是有一定的编程或者Unity基础的。

    一、基础

    1. Unity3D 5.3.5可编译运行
    2. 脚本采用C#脚本编写
    3. 模型是FBX模型文件
      这里写图片描述
    4. 运行结果图
      这里写图片描述
    5. 性子急的或者有基础可以直接下载源码进行研究

      Unity3D动画例子源码

    二、Generic动画

    Generic是新的动画系统,它就是支持非人形的动画,建议使用它。但是它不能向Humanoid重定向动画。
    1. 设置资源格式
    选中Generic_Animation资源,在显示面板那里 Rig选择Generic
    这里写图片描述
    2. 创建AnimatorController
    这里写图片描述
    最后命名为GenericController放在Anim文件夹下面
    在Swordman的目录下,选择Generic_Animation,然后把里面自己需要用到的动作添加到控制器去
    这里写图片描述
    先拖一个Idle进去,再拖Run进来,如下图
    这里写图片描述
    3. 关联Idle和Run动作
    需要给这两个动作设置相关参数,方便我们程序调用
    这里写图片描述
    在Idle上右键- — 选择 Make Transition,然后控制鼠标箭头连到Run
    同样的Run也关联到Idle
    这里写图片描述
    4. 增加动作之间的状态
    动作配置好了之后,我们就要动作设置状态了,这里我们简单设置,增加一个布尔值 Move来表示移动和停止。
    那么Move为true的时候,表示需要移动了,则是从Idle切换到Run,false则是从Run切换到Idle
    首先在Animator的paramer那里增加一个布尔的Move参数(没有之前是 list is Empty)
    这里写图片描述
    点击旁边的+号,然后选择Bool类型,最后命名为Move
    这里写图片描述
    5. 设置动作之间的状态
    选中Idle到Run的箭头,然后在旁边设置move属性为true
    这里写图片描述
    Run到Idle的箭头,设置Move属性为false
    这里写图片描述
    6. 添加人物模型
    前面的基础动作配置好了,那么就在场景中增加模型吧
    首先把Swordman_No_Animation拖放到舞台,然后命名为GenericAnimation
    这里写图片描述
    这里写图片描述
    刚拖进入是背面的,那么设置一下Y-180。
    把Unity自带的Animation给删除掉(这个其实就是Legacy动画要用到了,后面再讲)
    然后给增加一个Animator组建,在Add Component那里搜索Animator,然后点击添加进去
    这里写图片描述
    同时给这个组件设置相关参数了。
    Controller和Avatar分别给添加上,点击那个小圆圈会出现选项了。最后添加GenericAnimMgr脚本。
    这里写图片描述
    到这里,暂时需要直接在Unity设置的东西就差不多了,那么开始写C#脚本了
    7. C#控制脚本
    脚本比较简单,主要是通过Animator 组件来数值Move的true和false

    using UnityEngine;
    using System.Collections;
    /// <summary>
    /// 使用Animator控制角色动作的例子
    /// </summary>
    public class GenericAnimMgr : MonoBehaviour 
    {
        private Animator animator;
        private bool isRun;
        // Use this for initialization
        void Start ()
        {
            animator = this.GetComponent<Animator>();
            //默认播放 idle
            animator.SetBool("Move", false);
        }
    
        // Update is called once per frame
        void Update () 
        {
            if (Input.GetKeyDown(KeyCode.Space))
            {
    
                if (isRun)
                    //平滑切换
                    animator.SetBool("Move", false);
                else
                    animator.SetBool("Move", true);
                isRun = !isRun;
            }
         }
    }

    三、Legacy动画

    legacy是老的动画系统,不多说。在引入Mecanim之前,Unity使用了自己的动画系统以便向后兼容,此系统仍然可用。 使用旧版动画系统主要是为了方便继续开发没有使用新Mecanim系统的项目。 然而,不推荐再在新项目中使用旧版动画系统。
    1. 添加模型
    步骤和Generic一样,把Swordman_No_Animation拖放到舞台,然后命名为LegacyAnimation
    2.添加动作
    直接在Animation组件里进行添加,不需要额外的其他控制器制作
    Animation属性,是默认出现的动作,这里选择Idle
    Animations表示这个模型有多少动作,这里选择2,同时增加Idle和Run
    3.添加LegacyAnimMgr脚本
    最后如何图
    这里写图片描述
    4. C#脚本

    using System;
    using UnityEngine;
    using System.Collections;
    /// <summary>
    /// 动画控制器(基于Legacy的动画类型)
    /// by sodaChen
    /// </summary>
    public class LegacyAnimMgr : MonoBehaviour 
    {
        /** 动画控制器 **/
        private Animation anim;
        private bool isRun;
        void Start () 
        {
            //获取到动画组件
            anim = this.GetComponent<Animation>();
            //默认播放站立动作(如果组件有配置,这里则可以不用写)
            //anim.Play("Sword-Idle");  
        }
    
        // Update is called once per frame
        void Update () 
        {
            //通过不同的键盘控制来播放指定的动画
            if (Input.GetKeyDown(KeyCode.Space))
            {
    
                if (isRun)
                    anim.CrossFade("Sword-Idle");
                else
                    //角色跑起来
                    anim.Play("Sword-Run");
                isRun = !isRun;
            }
            if (Input.GetKeyDown(KeyCode.LeftAlt))
            {
                //渐变到站立动作,有个缓冲动作。具体看API描述作用
                anim.CrossFade("Sword-Idle");
                //直接切换站立动作
                //anim.Play("Sword-Idle");  
            }
        }
    }
    

    四、总结

    Unity做动画还是比较简单的,其实还有Humanoid动画,就是新的人形重定向动画系统。不过这里的制作还是比较依赖Unity,小游戏之类的,动画模型不多,还可以人力去做,去设置之间的关系。在实际开发手游项目过程,我们会采用一些脚本自动打包这些模型动作,以及自动绑定相关的脚本,这样维护性就高很多了。

    展开全文
  • 测试用例模板和例子

    万次阅读 多人点赞 2017-02-14 15:58:31
    这个例子可能有些极端,但测试用例需求设计同步的情况在实际开发过程中确是屡见不鲜的,测试用例文档是“活的”文档,这一点应该被测试工程师牢记。   4 、测试用例应该包含实际的数据; ...
  • 这是一个简单的一维回归的例子,以两种不同的方式计算: 一个是无噪音的情况 另一个是噪音已知的情况 在这两种情况下的核参数都由最大似然法估计得到。 实例代码 import numpy as np from matplotlib import ...
  • Mybatis嵌套查询的原理与例子

    千次阅读 2014-02-24 15:11:50
    最下面的3行数据,是用SQL查询出来的结果,下图是该数据JAVA对象的对应关系。 生成RowKey的方法:RowKey是为了唯一确定一条数据。如果用户设置了主键,就用主键名+值生成RowKey,如RowKey1用的 id1(还有一...
  • struts2的配置一个简单的例子

    万次阅读 多人点赞 2016-09-29 12:16:20
    简介这篇文章主要如何在eclipse中使用struts2,文章使用的struts2的版本是2.5.2,会其他的版本有一小点的差别,文章里已经说明。例子的完整源码在文末,亲测没有任何错误。struts2 下载官网下载地址 最新版是...
  • 关于闭包究竟是什么,闭包干嘛用的,网上各种回答也是五花八门,动动就扯到隐匿变量/内存泄漏这些概念,让没有C基础的初学者越看越晕,我能说那些是错的,不过显然对新手太友好。曾几何时我也是被那些个...
  • 如果 region 里面包含大量的大型对象,则该region中最后一个具有巨型对象的区域区域末端之间的空间将不会使用。如果有多个这样的大型对象,这个未使用的空间可能导致堆碎片化。针对这个原因,调整的方法一般是修改...
  • 例子: UGC: User-generated Content 用户生产内容。是指用户将自己原创的内容通过互联网进行展示或者给其他用户。它是一种以Web2.0概念而新兴的方式,现在由原来的以下载为主变成下载上传并重。 UGC有两层组织...
  • json例子

    千次阅读 2007-05-14 21:02:00
    本来一直觉得这么基础的功能是没有什么好拿出来的,今天网友聊天发现,由于缺乏对json的理解,很多人都还在继续带着自己的项目往ajax的方向进军,而完全知道有一个好得多的替代品。所以写下这么个demo给大家...
  • Google 的开源技术protobuf 简介与例子

    万次阅读 多人点赞 2010-05-17 10:11:00
    本文来自CSDN博客:http://blog.csdn.net/program_think/archive/2009/05/31/4229773.aspx 今天来介绍一下...本来俺在构思“生产者/消费者模式 ”系列的下一个帖子:关于生产者消费者之间的数据传输格式。由于
  • Linux下VCSVerdi联合仿真简易教程及例子示范

    千次阅读 多人点赞 2020-07-22 11:42:47
    最近在公司实习,最近也恰好在学习Linux下的IC设计环境,涉及到了VCSVerdi联合仿真等内容,也切身感觉到,学校学习的内容是如此的不同,此篇便来下: VCS,Verdi是什么,为何要用VCSVerdi? 用一个简短的...
  • 一个例子搞懂宽表窄表的区别

    万次阅读 多人点赞 2018-11-13 11:28:45
    由于把不同的内容都放在同一张表存储,宽表已经符合三范式的模型设计规范,随之带来的主要坏处就是数据的大量冗余,之相对应的好处就是查询性能的提高便捷。这种宽表的设计广泛应用于数据挖掘模型训练前的数据...
  • XMLRPC简介java例子

    千次阅读 2011-09-22 11:10:49
    1.xml rpc是什么 ...xml rpc是使用http协议做为传输协议的rpc机制,使用xml文本的方式传输命令数据。 一个rpc系统,必然包括2个部分:1.rpc client,用来向rpc server调用方法,并接收方法的返回
  • 本博客一直以来的宗旨就是:用最简单的方式清楚复杂的问题。 因为本人也很菜所以也没法太复杂HHHHHH...... 所以如果哪天某个大神看到了觉得的有问题欢迎指出。...直接拿例子算了- -   using Sy...
  • 一个理解 wait() notify() 的例子  下面是我原来在 CSDN 论坛上看到的一个贴子,涉及到同步, wait(), notify() 等概念的理解,我试着根据原来的一些回复 Think in Java 上的相关概念将 wait() notify() 这...
  • FlasCC例子研究之Animation

    千次阅读 2013-05-17 00:47:00
    FlasCC例子研究之Animation 上几个例子向我们展示了,如何在main()函数里用C++AS3进行交互。 但是,如果我们想在C++中...因为这会把Flash Player的线程阻塞,所有的图像,声音输入就都能被处...
  • 信号量基础两个经典例子

    千次阅读 2014-10-05 15:11:45
    信号量基础两个经典例子 信号量(semaphore) 用于进程中传递信号的一个整数值。 三个操作: 1、一个信号量可以初始化为非负值 2、semWait操作可以使信号量减1,若信号量的值为负,则执行semWait的进程被阻塞。否则...
  • Openlayers入门经典例子

    万次阅读 多人点赞 2013-12-11 15:18:15
    openlayers入门经典例子
  • nginx入门简单的反向代理例子

    千次阅读 2018-05-17 20:56:12
    nginx可以作为反向代理负载均衡服务器,这里只nginx的反向代理首先我的环境是debian做的deepin1.首先安装nginx,因为debian是由ubantu改来,安装命令是apt-get,redhat是yum命令在命令行输入 apt-get install ...
  • 结合例子理解排他(exclusive)锁共享(shared...但我们还是先讲例子再讲锁的定义. 首先,根据锁类型划分有排他(exclusive)锁共享(shared)锁。 下面举例: 通过DML语句对一张表的某一行数据进行修改,一个事
  • 转载请注明出处:王亟亟的大牛之路按照国际惯例先安利:https://github.com/ddwhan0123/Useful-Open-Source-Android上礼拜有简单提到v-if v-for 没有深入研究,这一篇就更详细讲讲这俩指令(万物到底就是...
  • React Native 音频录制例子来解惑入门

    千次阅读 2017-07-10 09:36:24
    React Native 音频录制...从indexandroidjs开始起 说说怎么用开源项目提供的组件 如何测试 总结前言 本文基于开源Demo:https://github.com/zmxv/react-native-sound,通过这个例子学习怎么开发React Native App.
  • Joda-Time简介简单使用例子

    千次阅读 2012-10-29 23:42:47
    由于大四开学忙着毕业的东西,博客也很久没更新了。最近刚闲下来点。上网看看无意中看到这篇文章,其实之前也压根没听说过...不定当时就发现它了,看来自己还挺笨的哈),要是早点知道这个工具包,可能当时也就没这么
  • svn的merge使用例子

    万次阅读 多人点赞 2014-03-22 17:46:53
    svn的merge使用例子
  • 一个语音识别的例子

    千次阅读 2012-09-09 16:27:13
     昨天搞定了SDK中的那个例子,接着想按照文档自己来写一个,但是.....直接用文档里的代码能调出来东西的话,简直就是奇迹。  所以就花了一些时间,完成了这个语音听写的例子例子中,点击最下面的button可以开始...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 817,761
精华内容 327,104
关键字:

不与自己讲和的例子